2 // GroupingCollection.cs: Represents group of BuildItemGroup,
3 // BuildPropertyGroup and BuildChoose.
6 // Marek Sieradzki (marek.sieradzki@gmail.com)
8 // (C) 2005 Marek Sieradzki
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections;
31 using System.Collections.Generic;
33 namespace Microsoft.Build.BuildEngine {
34 internal class GroupingCollection : IEnumerable {
42 LinkedList <object> list;
43 LinkedListNode <object> add_iterator;
45 public GroupingCollection (Project project)
47 list = new LinkedList <object> ();
49 this.project = project;
52 public IEnumerator GetChooseEnumerator ()
54 foreach (object o in list)
59 public IEnumerator GetEnumerator ()
61 return list.GetEnumerator ();
64 public IEnumerator GetImportEnumerator ()
66 foreach (object o in list)
71 public IEnumerator GetItemGroupAndChooseEnumerator ()
73 foreach (object o in list)
74 if (o is BuildItemGroup || o is BuildPropertyGroup)
78 public IEnumerator GetItemGroupEnumerator ()
80 foreach (object o in list)
81 if (o is BuildItemGroup)
85 public IEnumerator GetPropertyGroupAndChooseEnumerator ()
87 foreach (object o in list)
88 if (o is BuildPropertyGroup || o is BuildChoose)
92 public IEnumerator GetPropertyGroupEnumerator ()
94 foreach (object o in list)
95 if (o is BuildPropertyGroup)
99 internal void Add (BuildPropertyGroup bpg)
101 bpg.GroupingCollection = this;
103 if (add_iterator == null)
106 list.AddAfter (add_iterator, bpg);
107 add_iterator = add_iterator.Next;
111 internal void Add (BuildItemGroup big)
114 if (add_iterator == null)
117 list.AddAfter (add_iterator, big);
118 add_iterator = add_iterator.Next;
122 internal void Add (BuildChoose bc)
125 if (add_iterator == null)
128 list.AddAfter (add_iterator, bc);
129 add_iterator = add_iterator.Next;
133 internal void Add (Import import)
136 if (add_iterator == null)
137 list.AddLast (import);
139 list.AddAfter (add_iterator, import);
140 add_iterator = add_iterator.Next;
144 internal void Remove (BuildItemGroup big)
146 if (big.ParentProject != project)
147 throw new InvalidOperationException (
148 "The \"BuildItemGroup\" object specified does not belong to the correct \"Project\" object.");
154 internal void Remove (BuildPropertyGroup bpg)
156 // FIXME: add bpg.Detach ();
157 bpg.XmlElement.ParentNode.RemoveChild (bpg.XmlElement);
161 internal void Evaluate ()
163 Evaluate (EvaluationType.Property);
164 Evaluate (EvaluationType.Item);
165 Evaluate (EvaluationType.Choose);
168 internal void Evaluate (EvaluationType type)
171 BuildPropertyGroup bpg;
172 LinkedListNode <object> evaluate_iterator;
174 if (type == EvaluationType.Property) {
175 evaluate_iterator = list.First;
176 add_iterator = list.First;
178 while (evaluate_iterator != null) {
179 if (evaluate_iterator.Value is BuildPropertyGroup) {
180 bpg = (BuildPropertyGroup) evaluate_iterator.Value;
181 project.PushThisFileProperty (bpg.DefinedInFileName);
183 if (ConditionParser.ParseAndEvaluate (bpg.Condition, project))
186 project.PopThisFileProperty ();
190 // if it wasn't moved by adding anything because of evaluating a Import shift it
191 if (add_iterator == evaluate_iterator)
192 add_iterator = add_iterator.Next;
194 evaluate_iterator = evaluate_iterator.Next;
196 } else if (type == EvaluationType.Item) {
197 evaluate_iterator = list.First;
198 add_iterator = list.First;
200 while (evaluate_iterator != null) {
201 if (evaluate_iterator.Value is BuildItemGroup) {
202 big = (BuildItemGroup) evaluate_iterator.Value;
203 project.PushThisFileProperty (big.DefinedInFileName);
205 if (ConditionParser.ParseAndEvaluate (big.Condition, project))
208 project.PopThisFileProperty ();
212 evaluate_iterator = evaluate_iterator.Next;
214 } else if (type == EvaluationType.Choose) {
215 evaluate_iterator = list.First;
216 add_iterator = list.First;
218 while (evaluate_iterator != null) {
219 if (evaluate_iterator.Value is BuildChoose) {
220 BuildChoose bc = (BuildChoose)evaluate_iterator.Value;
221 project.PushThisFileProperty (bc.DefinedInFileName);
223 bool whenUsed = false;
224 foreach (BuildWhen bw in bc.Whens) {
225 if (ConditionParser.ParseAndEvaluate (bw.Condition, project)) {
231 if (!whenUsed && bc.Otherwise != null &&
232 ConditionParser.ParseAndEvaluate (bc.Otherwise.Condition, project)) {
233 bc.Otherwise.Evaluate ();
236 project.PopThisFileProperty ();
240 evaluate_iterator = evaluate_iterator.Next;
247 internal int Imports {
248 get { return this.imports; }
251 internal int ItemGroups {
252 get { return this.itemGroups; }
255 internal int PropertyGroups {
256 get { return this.propertyGroups; }
259 internal int Chooses {
260 get { return this.chooses; }
264 enum EvaluationType {