.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

199 lines
4.9 KiB

// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.VB
{
/// <summary>
/// Represents the children of an AstNode that have a specific role.
/// </summary>
public class AstNodeCollection<T> : ICollection<T> where T : AstNode
{
readonly AstNode node;
readonly Role<T> role;
public AstNodeCollection(AstNode node, Role<T> role)
{
if (node == null)
throw new ArgumentNullException("node");
if (role == null)
throw new ArgumentNullException("role");
this.node = node;
this.role = role;
}
public int Count {
get {
int count = 0;
for (AstNode cur = node.FirstChild; cur != null; cur = cur.NextSibling) {
if (cur.Role == role)
count++;
}
return count;
}
}
public void Add(T element)
{
node.AddChild(element, role);
}
public void AddRange(IEnumerable<T> nodes)
{
// Evaluate 'nodes' first, since it might change when we add the new children
// Example: collection.AddRange(collection);
if (nodes != null) {
foreach (T node in nodes.ToList())
Add(node);
}
}
public void AddRange(T[] nodes)
{
// Fast overload for arrays - we don't need to create a copy
if (nodes != null) {
foreach (T node in nodes)
Add(node);
}
}
public void ReplaceWith(IEnumerable<T> nodes)
{
// Evaluate 'nodes' first, since it might change when we call Clear()
// Example: collection.ReplaceWith(collection);
if (nodes != null)
nodes = nodes.ToList();
Clear();
foreach (T node in nodes)
Add(node);
}
public void MoveTo(ICollection<T> targetCollection)
{
foreach (T node in this) {
node.Remove();
targetCollection.Add(node);
}
}
public bool Contains(T element)
{
return element != null && element.Parent == node && element.Role == role;
}
public bool Remove(T element)
{
if (Contains(element)) {
element.Remove();
return true;
} else {
return false;
}
}
public void CopyTo(T[] array, int arrayIndex)
{
foreach (T item in this)
array[arrayIndex++] = item;
}
public void Clear()
{
foreach (T item in this)
item.Remove();
}
bool ICollection<T>.IsReadOnly {
get { return false; }
}
public IEnumerator<T> GetEnumerator()
{
AstNode next;
for (AstNode cur = node.FirstChild; cur != null; cur = next) {
Debug.Assert(cur.Parent == node);
// Remember next before yielding cur.
// This allows removing/replacing nodes while iterating through the list.
next = cur.NextSibling;
if (cur.Role == role)
yield return (T)cur;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#region Equals and GetHashCode implementation
public override int GetHashCode()
{
return node.GetHashCode() ^ role.GetHashCode();
}
public override bool Equals(object obj)
{
AstNodeCollection<T> other = obj as AstNodeCollection<T>;
if (other == null)
return false;
return this.node == other.node && this.role == other.role;
}
#endregion
internal bool DoMatch(AstNodeCollection<T> other, Match match)
{
// TODO : does not compile (ask Daniel)!
// Stack<AstNode> patternStack = new Stack<AstNode>();
// Stack<Pattern.PossibleMatch> stack = new Stack<Pattern.PossibleMatch>();
// patternStack.Push(this.node.FirstChild);
// stack.Push(new Pattern.PossibleMatch(other.node.FirstChild, match.CheckPoint()));
// while (stack.Count > 0) {
// AstNode cur1 = patternStack.Pop();
// AstNode cur2 = stack.Peek().NextOther;
// match.RestoreCheckPoint(stack.Pop().Checkpoint);
// bool success = true;
// while (cur1 != null && success) {
// while (cur1 != null && cur1.Role != role)
// cur1 = cur1.NextSibling;
// while (cur2 != null && cur2.Role != role)
// cur2 = cur2.NextSibling;
// if (cur1 == null)
// break;
//
// Debug.Assert(stack.Count == patternStack.Count);
// success = cur1.DoMatchCollection(role, cur2, match, stack);
// Debug.Assert(stack.Count >= patternStack.Count);
// while (stack.Count > patternStack.Count)
// patternStack.Push(cur1.NextSibling);
//
// cur1 = cur1.NextSibling;
// if (cur2 != null)
// cur2 = cur2.NextSibling;
// }
// while (cur2 != null && cur2.Role != role)
// cur2 = cur2.NextSibling;
// if (success && cur2 == null)
// return true;
// }
// return false;
throw new NotImplementedException();
}
public void InsertAfter(T existingItem, T newItem)
{
node.InsertChildAfter(existingItem, newItem, role);
}
public void InsertBefore(T existingItem, T newItem)
{
node.InsertChildBefore(existingItem, newItem, role);
}
}
}