Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Ast/AstNodeCollection.cs @ 11937

Last change on this file since 11937 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 6.2 KB
Line 
1// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.Collections;
21using System.Collections.Generic;
22using System.Diagnostics;
23using System.Linq;
24using ICSharpCode.NRefactory.PatternMatching;
25
26namespace ICSharpCode.NRefactory.CSharp
27{
28  /// <summary>
29  /// Represents the children of an AstNode that have a specific role.
30  /// </summary>
31  public class AstNodeCollection<T> : ICollection<T>
32    #if NET_4_5
33    , IReadOnlyCollection<T>
34    #endif
35    where T : AstNode
36  {
37    readonly AstNode node;
38    readonly Role<T> role;
39   
40    public AstNodeCollection(AstNode node, Role<T> role)
41    {
42      if (node == null)
43        throw new ArgumentNullException("node");
44      if (role == null)
45        throw new ArgumentNullException("role");
46      this.node = node;
47      this.role = role;
48    }
49   
50    public int Count {
51      get {
52        int count = 0;
53        uint roleIndex = role.Index;
54        for (AstNode cur = node.FirstChild; cur != null; cur = cur.NextSibling) {
55          if (cur.RoleIndex == roleIndex)
56            count++;
57        }
58        return count;
59      }
60    }
61   
62    public void Add(T element)
63    {
64      node.AddChild(element, role);
65    }
66   
67    public void AddRange(IEnumerable<T> nodes)
68    {
69      // Evaluate 'nodes' first, since it might change when we add the new children
70      // Example: collection.AddRange(collection);
71      if (nodes != null) {
72        foreach (T node in nodes.ToList())
73          Add(node);
74      }
75    }
76   
77    public void AddRange(T[] nodes)
78    {
79      // Fast overload for arrays - we don't need to create a copy
80      if (nodes != null) {
81        foreach (T node in nodes)
82          Add(node);
83      }
84    }
85   
86    public void ReplaceWith(IEnumerable<T> nodes)
87    {
88      // Evaluate 'nodes' first, since it might change when we call Clear()
89      // Example: collection.ReplaceWith(collection);
90      if (nodes != null)
91        nodes = nodes.ToList();
92      Clear();
93      if (nodes != null) {
94        foreach (T node in nodes)
95          Add(node);
96      }
97    }
98   
99    public void MoveTo(ICollection<T> targetCollection)
100    {
101      if (targetCollection == null)
102        throw new ArgumentNullException("targetCollection");
103      foreach (T node in this) {
104        node.Remove();
105        targetCollection.Add(node);
106      }
107    }
108   
109    public bool Contains(T element)
110    {
111      return element != null && element.Parent == node && element.RoleIndex == role.Index;
112    }
113   
114    public bool Remove(T element)
115    {
116      if (Contains(element)) {
117        element.Remove();
118        return true;
119      } else {
120        return false;
121      }
122    }
123   
124    public void CopyTo(T[] array, int arrayIndex)
125    {
126      foreach (T item in this)
127        array[arrayIndex++] = item;
128    }
129   
130    public void Clear()
131    {
132      foreach (T item in this)
133        item.Remove();
134    }
135   
136    /// <summary>
137    /// Returns the first element for which the predicate returns true,
138    /// or the null node (AstNode with IsNull=true) if no such object is found.
139    /// </summary>
140    public T FirstOrNullObject(Func<T, bool> predicate = null)
141    {
142      foreach (T item in this)
143        if (predicate == null || predicate(item))
144          return item;
145      return role.NullObject;
146    }
147   
148    /// <summary>
149    /// Returns the last element for which the predicate returns true,
150    /// or the null node (AstNode with IsNull=true) if no such object is found.
151    /// </summary>
152    public T LastOrNullObject(Func<T, bool> predicate = null)
153    {
154      T result = role.NullObject;
155      foreach (T item in this)
156        if (predicate == null || predicate(item))
157          result = item;
158      return result;
159    }
160   
161    bool ICollection<T>.IsReadOnly {
162      get { return false; }
163    }
164   
165    public IEnumerator<T> GetEnumerator()
166    {
167      uint roleIndex = role.Index;
168      AstNode next;
169      for (AstNode cur = node.FirstChild; cur != null; cur = next) {
170        Debug.Assert(cur.Parent == node);
171        // Remember next before yielding cur.
172        // This allows removing/replacing nodes while iterating through the list.
173        next = cur.NextSibling;
174        if (cur.RoleIndex == roleIndex)
175          yield return (T)cur;
176      }
177    }
178   
179    IEnumerator IEnumerable.GetEnumerator()
180    {
181      return GetEnumerator();
182    }
183   
184    #region Equals and GetHashCode implementation
185    public override int GetHashCode()
186    {
187      return node.GetHashCode() ^ role.GetHashCode();
188    }
189   
190    public override bool Equals(object obj)
191    {
192      AstNodeCollection<T> other = obj as AstNodeCollection<T>;
193      if (other == null)
194        return false;
195      return this.node == other.node && this.role == other.role;
196    }
197    #endregion
198   
199    internal bool DoMatch(AstNodeCollection<T> other, Match match)
200    {
201      return Pattern.DoMatchCollection(role, node.FirstChild, other.node.FirstChild, match);
202    }
203   
204    public void InsertAfter(T existingItem, T newItem)
205    {
206      node.InsertChildAfter(existingItem, newItem, role);
207    }
208   
209    public void InsertBefore(T existingItem, T newItem)
210    {
211      node.InsertChildBefore(existingItem, newItem, role);
212    }
213   
214    /// <summary>
215    /// Applies the <paramref name="visitor"/> to all nodes in this collection.
216    /// </summary>
217    public void AcceptVisitor(IAstVisitor visitor)
218    {
219      uint roleIndex = role.Index;
220      AstNode next;
221      for (AstNode cur = node.FirstChild; cur != null; cur = next) {
222        Debug.Assert(cur.Parent == node);
223        // Remember next before yielding cur.
224        // This allows removing/replacing nodes while iterating through the list.
225        next = cur.NextSibling;
226        if (cur.RoleIndex == roleIndex)
227          cur.AcceptVisitor(visitor);
228      }
229    }
230  }
231}
Note: See TracBrowser for help on using the repository browser.