Browse Source

Enable automatic removal when replacing a node with its own descendant.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
57522bf091
  1. 44
      ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs

44
ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs

@ -129,6 +129,26 @@ namespace ICSharpCode.NRefactory.CSharp
} }
} }
/// <summary>
/// Gets the ancestors of this node (excluding this node itself)
/// </summary>
public IEnumerable<AstNode> Ancestors {
get {
for (AstNode cur = parent; cur != null; cur = cur.parent) {
yield return cur;
}
}
}
/// <summary>
/// Gets all descendants of this node (excluding this node itself).
/// </summary>
public IEnumerable<AstNode> Descendants {
get {
return Utils.TreeTraversal.PreOrder(this.Children, n => n.Children);
}
}
/// <summary> /// <summary>
/// Gets the first child with the specified role. /// Gets the first child with the specified role.
/// Returns the role's null object if the child is not found. /// Returns the role's null object if the child is not found.
@ -291,20 +311,27 @@ namespace ICSharpCode.NRefactory.CSharp
Remove(); Remove();
return; return;
} }
if (this.parent == null) { if (newNode == this)
return; // nothing to do...
if (parent == null) {
throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node");
} }
if (newNode.parent != null) {
// TODO: what if newNode is used within *this* tree?
// e.g. "parenthesizedExpr.ReplaceWith(parenthesizedExpr.Expression);"
// We'll probably want to allow that.
throw new ArgumentException ("Node is already used in another tree.", "newNode");
}
// Because this method doesn't statically check the new node's type with the role, // Because this method doesn't statically check the new node's type with the role,
// we perform a runtime test: // we perform a runtime test:
if (!role.IsValid(newNode)) { if (!role.IsValid(newNode)) {
throw new ArgumentException (string.Format("The new node '{0}' is not valid in the role {1}", newNode.GetType().Name, role.ToString()), "newNode"); throw new ArgumentException (string.Format("The new node '{0}' is not valid in the role {1}", newNode.GetType().Name, role.ToString()), "newNode");
} }
if (newNode.parent != null) {
// newNode is used within this tree?
if (newNode.Ancestors.Contains(this)) {
// e.g. "parenthesizedExpr.ReplaceWith(parenthesizedExpr.Expression);"
// enable automatic removal
newNode.Remove();
} else {
throw new ArgumentException ("Node is already used in another tree.", "newNode");
}
}
newNode.parent = parent; newNode.parent = parent;
newNode.role = role; newNode.role = role;
newNode.prevSibling = prevSibling; newNode.prevSibling = prevSibling;
@ -335,6 +362,9 @@ namespace ICSharpCode.NRefactory.CSharp
{ {
if (replaceFunction == null) if (replaceFunction == null)
throw new ArgumentNullException("replaceFunction"); throw new ArgumentNullException("replaceFunction");
if (parent == null) {
throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node");
}
AstNode oldParent = parent; AstNode oldParent = parent;
AstNode oldSuccessor = nextSibling; AstNode oldSuccessor = nextSibling;
Role oldRole = role; Role oldRole = role;

Loading…
Cancel
Save