a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
276 lines
6.6 KiB
C#
276 lines
6.6 KiB
C#
//
|
|
// GroupingCollection.cs: Represents group of BuildItemGroup,
|
|
// BuildPropertyGroup and BuildChoose.
|
|
//
|
|
// Authors:
|
|
// Marek Sieradzki (marek.sieradzki@gmail.com)
|
|
// Marek Safar (marek.safar@gmail.com)
|
|
//
|
|
// (C) 2005 Marek Sieradzki
|
|
// Copyright (c) 2014 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;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Microsoft.Build.BuildEngine {
|
|
internal class GroupingCollection : IEnumerable {
|
|
|
|
int imports;
|
|
int itemGroups;
|
|
Project project;
|
|
int propertyGroups;
|
|
int chooses;
|
|
|
|
LinkedList <object> list;
|
|
LinkedListNode <object> add_iterator;
|
|
|
|
public GroupingCollection (Project project)
|
|
{
|
|
list = new LinkedList <object> ();
|
|
add_iterator = null;
|
|
this.project = project;
|
|
}
|
|
|
|
public IEnumerator GetChooseEnumerator ()
|
|
{
|
|
foreach (object o in list)
|
|
if (o is BuildChoose)
|
|
yield return o;
|
|
}
|
|
|
|
public IEnumerator GetEnumerator ()
|
|
{
|
|
return list.GetEnumerator ();
|
|
}
|
|
|
|
public IEnumerator GetImportEnumerator ()
|
|
{
|
|
foreach (object o in list)
|
|
if (o is Import)
|
|
yield return o;
|
|
}
|
|
|
|
public IEnumerator GetItemGroupAndChooseEnumerator ()
|
|
{
|
|
foreach (object o in list)
|
|
if (o is BuildItemGroup || o is BuildPropertyGroup)
|
|
yield return o;
|
|
}
|
|
|
|
public IEnumerator GetItemGroupEnumerator ()
|
|
{
|
|
foreach (object o in list)
|
|
if (o is BuildItemGroup)
|
|
yield return o;
|
|
}
|
|
|
|
public IEnumerator GetPropertyGroupAndChooseEnumerator ()
|
|
{
|
|
foreach (object o in list)
|
|
if (o is BuildPropertyGroup || o is BuildChoose)
|
|
yield return o;
|
|
}
|
|
|
|
public IEnumerator GetPropertyGroupEnumerator ()
|
|
{
|
|
foreach (object o in list)
|
|
if (o is BuildPropertyGroup)
|
|
yield return o;
|
|
}
|
|
|
|
internal void Add (BuildPropertyGroup bpg)
|
|
{
|
|
bpg.GroupingCollection = this;
|
|
propertyGroups++;
|
|
if (add_iterator == null)
|
|
list.AddLast (bpg);
|
|
else {
|
|
list.AddAfter (add_iterator, bpg);
|
|
add_iterator = add_iterator.Next;
|
|
}
|
|
}
|
|
|
|
internal void Add (BuildItemGroup big)
|
|
{
|
|
itemGroups++;
|
|
if (add_iterator == null)
|
|
list.AddLast (big);
|
|
else {
|
|
list.AddAfter (add_iterator, big);
|
|
add_iterator = add_iterator.Next;
|
|
}
|
|
}
|
|
|
|
internal void Add (BuildChoose bc)
|
|
{
|
|
chooses++;
|
|
if (add_iterator == null)
|
|
list.AddLast (bc);
|
|
else {
|
|
list.AddAfter (add_iterator, bc);
|
|
add_iterator = add_iterator.Next;
|
|
}
|
|
}
|
|
|
|
internal void Add (Import import)
|
|
{
|
|
imports++;
|
|
if (add_iterator == null)
|
|
list.AddLast (import);
|
|
else {
|
|
list.AddAfter (add_iterator, import);
|
|
add_iterator = add_iterator.Next;
|
|
}
|
|
}
|
|
|
|
internal void Remove (BuildItemGroup big)
|
|
{
|
|
if (big.ParentProject != project)
|
|
throw new InvalidOperationException (
|
|
"The \"BuildItemGroup\" object specified does not belong to the correct \"Project\" object.");
|
|
|
|
big.Detach ();
|
|
list.Remove (big);
|
|
}
|
|
|
|
internal void Remove (BuildPropertyGroup bpg)
|
|
{
|
|
// FIXME: add bpg.Detach ();
|
|
bpg.XmlElement.ParentNode.RemoveChild (bpg.XmlElement);
|
|
list.Remove (bpg);
|
|
}
|
|
|
|
internal void Evaluate ()
|
|
{
|
|
Evaluate (EvaluationType.Property | EvaluationType.Choose);
|
|
Evaluate (EvaluationType.Item);
|
|
}
|
|
|
|
internal void Evaluate (EvaluationType type)
|
|
{
|
|
add_iterator = list.First;
|
|
|
|
for (var evaluate_iterator = list.First; evaluate_iterator != null; evaluate_iterator = evaluate_iterator.Next) {
|
|
var bpg = evaluate_iterator.Value as BuildPropertyGroup;
|
|
if (bpg != null) {
|
|
if ((type & EvaluationType.Property) != 0) {
|
|
EvaluateBuildPropertyGroup (bpg);
|
|
|
|
// if it wasn't moved by adding anything because of evaluating a Import shift it
|
|
if (add_iterator == evaluate_iterator)
|
|
add_iterator = add_iterator.Next;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
var big = evaluate_iterator.Value as BuildItemGroup;
|
|
if (big != null) {
|
|
if ((type & EvaluationType.Item) != 0)
|
|
EvaluateBuildItemGroup (big);
|
|
continue;
|
|
}
|
|
|
|
var bc = evaluate_iterator.Value as BuildChoose;
|
|
if (bc != null) {
|
|
if ((type & EvaluationType.Choose) != 0)
|
|
EvaluateBuildChoose (bc);
|
|
continue;
|
|
}
|
|
|
|
// Should not be reached
|
|
}
|
|
|
|
add_iterator = null;
|
|
}
|
|
|
|
void EvaluateBuildPropertyGroup (BuildPropertyGroup bpg)
|
|
{
|
|
project.PushThisFileProperty (bpg.DefinedInFileName);
|
|
try {
|
|
if (ConditionParser.ParseAndEvaluate (bpg.Condition, project))
|
|
bpg.Evaluate ();
|
|
} finally {
|
|
project.PopThisFileProperty ();
|
|
}
|
|
}
|
|
|
|
void EvaluateBuildItemGroup (BuildItemGroup big)
|
|
{
|
|
project.PushThisFileProperty (big.DefinedInFileName);
|
|
try {
|
|
if (ConditionParser.ParseAndEvaluate (big.Condition, project))
|
|
big.Evaluate ();
|
|
} finally {
|
|
project.PopThisFileProperty ();
|
|
}
|
|
}
|
|
|
|
void EvaluateBuildChoose (BuildChoose bc)
|
|
{
|
|
project.PushThisFileProperty (bc.DefinedInFileName);
|
|
try {
|
|
bool whenUsed = false;
|
|
foreach (BuildWhen bw in bc.Whens) {
|
|
if (ConditionParser.ParseAndEvaluate (bw.Condition, project)) {
|
|
bw.Evaluate ();
|
|
whenUsed = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!whenUsed && bc.Otherwise != null &&
|
|
ConditionParser.ParseAndEvaluate (bc.Otherwise.Condition, project)) {
|
|
bc.Otherwise.Evaluate ();
|
|
}
|
|
} finally {
|
|
project.PopThisFileProperty ();
|
|
}
|
|
}
|
|
|
|
internal int Imports {
|
|
get { return this.imports; }
|
|
}
|
|
|
|
internal int ItemGroups {
|
|
get { return this.itemGroups; }
|
|
}
|
|
|
|
internal int PropertyGroups {
|
|
get { return this.propertyGroups; }
|
|
}
|
|
|
|
internal int Chooses {
|
|
get { return this.chooses; }
|
|
}
|
|
}
|
|
|
|
[Flags]
|
|
enum EvaluationType {
|
|
Property = 1 << 0,
|
|
Item = 1 << 1,
|
|
Choose = 1 << 2,
|
|
|
|
Any = Property | Item | Choose
|
|
}
|
|
}
|