|
|
|
@ -1,4 +1,5 @@
@@ -1,4 +1,5 @@
|
|
|
|
|
//
|
|
|
|
|
#nullable enable |
|
|
|
|
//
|
|
|
|
|
// AstNode.cs
|
|
|
|
|
//
|
|
|
|
|
// Author:
|
|
|
|
@ -39,7 +40,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -39,7 +40,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
public abstract class AstNode : AbstractAnnotatable, IFreezable, INode, ICloneable |
|
|
|
|
{ |
|
|
|
|
// the Root role must be available when creating the null nodes, so we can't put it in the Roles class
|
|
|
|
|
internal static readonly Role<AstNode> RootRole = new Role<AstNode>("Root"); |
|
|
|
|
internal static readonly Role<AstNode?> RootRole = new Role<AstNode?>("Root", null); |
|
|
|
|
|
|
|
|
|
#region Null
|
|
|
|
|
public static readonly AstNode Null = new NullAstNode(); |
|
|
|
@ -73,7 +74,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -73,7 +74,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
return visitor.VisitNullNode(this, data); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) |
|
|
|
|
protected internal override bool DoMatch(AstNode? other, PatternMatching.Match match) |
|
|
|
|
{ |
|
|
|
|
return other == null || other.IsNull; |
|
|
|
|
} |
|
|
|
@ -81,7 +82,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -81,7 +82,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region PatternPlaceholder
|
|
|
|
|
public static implicit operator AstNode(PatternMatching.Pattern pattern) |
|
|
|
|
public static implicit operator AstNode?(PatternMatching.Pattern? pattern) |
|
|
|
|
{ |
|
|
|
|
return pattern != null ? new PatternPlaceholder(pattern) : null; |
|
|
|
|
} |
|
|
|
@ -114,23 +115,23 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -114,23 +115,23 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
return visitor.VisitPatternPlaceholder(this, child, data); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) |
|
|
|
|
protected internal override bool DoMatch(AstNode? other, PatternMatching.Match match) |
|
|
|
|
{ |
|
|
|
|
return child.DoMatch(other, match); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) |
|
|
|
|
bool PatternMatching.INode.DoMatchCollection(Role? role, PatternMatching.INode? pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) |
|
|
|
|
{ |
|
|
|
|
return child.DoMatchCollection(role, pos, match, backtrackingInfo); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
AstNode parent; |
|
|
|
|
AstNode prevSibling; |
|
|
|
|
AstNode nextSibling; |
|
|
|
|
AstNode firstChild; |
|
|
|
|
AstNode lastChild; |
|
|
|
|
AstNode? parent; |
|
|
|
|
AstNode? prevSibling; |
|
|
|
|
AstNode? nextSibling; |
|
|
|
|
AstNode? firstChild; |
|
|
|
|
AstNode? lastChild; |
|
|
|
|
|
|
|
|
|
// Flags, from least significant to most significant bits:
|
|
|
|
|
// - Role.RoleIndexBits: role index
|
|
|
|
@ -157,7 +158,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -157,7 +158,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
{ |
|
|
|
|
if (!IsFrozen) |
|
|
|
|
{ |
|
|
|
|
for (AstNode child = firstChild; child != null; child = child.nextSibling) |
|
|
|
|
for (AstNode? child = firstChild; child != null; child = child.nextSibling) |
|
|
|
|
child.Freeze(); |
|
|
|
|
flags |= frozenBit; |
|
|
|
|
} |
|
|
|
@ -197,7 +198,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -197,7 +198,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public AstNode Parent { |
|
|
|
|
public AstNode? Parent { |
|
|
|
|
get { return parent; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -224,19 +225,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -224,19 +225,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
flags = (flags & ~roleIndexMask) | role.Index; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public AstNode NextSibling { |
|
|
|
|
public AstNode? NextSibling { |
|
|
|
|
get { return nextSibling; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public AstNode PrevSibling { |
|
|
|
|
public AstNode? PrevSibling { |
|
|
|
|
get { return prevSibling; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public AstNode FirstChild { |
|
|
|
|
public AstNode? FirstChild { |
|
|
|
|
get { return firstChild; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public AstNode LastChild { |
|
|
|
|
public AstNode? LastChild { |
|
|
|
|
get { return lastChild; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -248,8 +249,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -248,8 +249,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
|
|
|
|
|
public IEnumerable<AstNode> Children { |
|
|
|
|
get { |
|
|
|
|
AstNode next; |
|
|
|
|
for (AstNode cur = firstChild; cur != null; cur = next) |
|
|
|
|
AstNode? next; |
|
|
|
|
for (AstNode? cur = firstChild; cur != null; cur = next) |
|
|
|
|
{ |
|
|
|
|
Debug.Assert(cur.parent == this); |
|
|
|
|
// Remember next before yielding cur.
|
|
|
|
@ -265,7 +266,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -265,7 +266,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// </summary>
|
|
|
|
|
public IEnumerable<AstNode> Ancestors { |
|
|
|
|
get { |
|
|
|
|
for (AstNode cur = parent; cur != null; cur = cur.parent) |
|
|
|
|
for (AstNode? cur = parent; cur != null; cur = cur.parent) |
|
|
|
|
{ |
|
|
|
|
yield return cur; |
|
|
|
|
} |
|
|
|
@ -277,7 +278,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -277,7 +278,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// </summary>
|
|
|
|
|
public IEnumerable<AstNode> AncestorsAndSelf { |
|
|
|
|
get { |
|
|
|
|
for (AstNode cur = this; cur != null; cur = cur.parent) |
|
|
|
|
for (AstNode? cur = this; cur != null; cur = cur.parent) |
|
|
|
|
{ |
|
|
|
|
yield return cur; |
|
|
|
|
} |
|
|
|
@ -298,18 +299,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -298,18 +299,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
get { return GetDescendantsImpl(true); } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public IEnumerable<AstNode> DescendantNodes(Func<AstNode, bool> descendIntoChildren = null) |
|
|
|
|
public IEnumerable<AstNode> DescendantNodes(Func<AstNode, bool>? descendIntoChildren = null) |
|
|
|
|
{ |
|
|
|
|
return GetDescendantsImpl(false, descendIntoChildren); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public IEnumerable<AstNode> DescendantNodesAndSelf(Func<AstNode, bool> descendIntoChildren = null) |
|
|
|
|
public IEnumerable<AstNode> DescendantNodesAndSelf(Func<AstNode, bool>? descendIntoChildren = null) |
|
|
|
|
{ |
|
|
|
|
return GetDescendantsImpl(true, descendIntoChildren); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IEnumerable<AstNode> GetDescendantsImpl(bool includeSelf, Func<AstNode, bool> descendIntoChildren = null) |
|
|
|
|
IEnumerable<AstNode> GetDescendantsImpl(bool includeSelf, Func<AstNode, bool>? descendIntoChildren = null) |
|
|
|
|
{ |
|
|
|
|
if (includeSelf) |
|
|
|
|
{ |
|
|
|
@ -318,9 +319,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -318,9 +319,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
yield break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Stack<AstNode> nextStack = new Stack<AstNode>(); |
|
|
|
|
Stack<AstNode?> nextStack = new Stack<AstNode?>(); |
|
|
|
|
nextStack.Push(null); |
|
|
|
|
AstNode pos = firstChild; |
|
|
|
|
AstNode? pos = firstChild; |
|
|
|
|
while (pos != null) |
|
|
|
|
{ |
|
|
|
|
// Remember next before yielding pos.
|
|
|
|
@ -339,7 +340,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -339,7 +340,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// Gets the first child with the specified role.
|
|
|
|
|
/// Returns the role's null object if the child is not found.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public T GetChildByRole<T>(Role<T> role) where T : AstNode |
|
|
|
|
public T GetChildByRole<T>(Role<T> role) where T : AstNode? |
|
|
|
|
{ |
|
|
|
|
if (role == null) |
|
|
|
|
throw new ArgumentNullException(nameof(role)); |
|
|
|
@ -352,12 +353,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -352,12 +353,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
return role.NullObject; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public T GetParent<T>() where T : AstNode |
|
|
|
|
public T? GetParent<T>() where T : AstNode |
|
|
|
|
{ |
|
|
|
|
return Ancestors.OfType<T>().FirstOrDefault(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public AstNode GetParent(Func<AstNode, bool> pred) |
|
|
|
|
public AstNode GetParent(Func<AstNode, bool>? pred) |
|
|
|
|
{ |
|
|
|
|
return Ancestors.FirstOrDefault(pred); |
|
|
|
|
} |
|
|
|
@ -392,7 +393,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -392,7 +393,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
AddChildUnsafe(child, role); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void AddChildWithExistingRole(AstNode child) |
|
|
|
|
public void AddChildWithExistingRole(AstNode? child) |
|
|
|
|
{ |
|
|
|
|
if (child == null || child.IsNull) |
|
|
|
|
return; |
|
|
|
@ -419,13 +420,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -419,13 +420,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
lastChild.nextSibling = child; |
|
|
|
|
lastChild!.nextSibling = child; |
|
|
|
|
child.prevSibling = lastChild; |
|
|
|
|
lastChild = child; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void InsertChildBefore<T>(AstNode nextSibling, T child, Role<T> role) where T : AstNode |
|
|
|
|
public void InsertChildBefore<T>(AstNode? nextSibling, T child, Role<T> role) where T : AstNode |
|
|
|
|
{ |
|
|
|
|
if (role == null) |
|
|
|
|
throw new ArgumentNullException(nameof(role)); |
|
|
|
@ -469,7 +470,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -469,7 +470,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
nextSibling.prevSibling = child; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void InsertChildAfter<T>(AstNode prevSibling, T child, Role<T> role) where T : AstNode |
|
|
|
|
public void InsertChildAfter<T>(AstNode? prevSibling, T child, Role<T> role) where T : AstNode |
|
|
|
|
{ |
|
|
|
|
InsertChildBefore((prevSibling == null || prevSibling.IsNull) ? firstChild : prevSibling.nextSibling, child, role); |
|
|
|
|
} |
|
|
|
@ -511,7 +512,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -511,7 +512,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Replaces this node with the new node.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public void ReplaceWith(AstNode newNode) |
|
|
|
|
public void ReplaceWith(AstNode? newNode) |
|
|
|
|
{ |
|
|
|
|
if (newNode == null || newNode.IsNull) |
|
|
|
|
{ |
|
|
|
@ -578,7 +579,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -578,7 +579,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
nextSibling = null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public AstNode ReplaceWith(Func<AstNode, AstNode> replaceFunction) |
|
|
|
|
public AstNode? ReplaceWith(Func<AstNode, AstNode?> replaceFunction) |
|
|
|
|
{ |
|
|
|
|
if (replaceFunction == null) |
|
|
|
|
throw new ArgumentNullException(nameof(replaceFunction)); |
|
|
|
@ -587,10 +588,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -587,10 +588,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); |
|
|
|
|
} |
|
|
|
|
AstNode oldParent = parent; |
|
|
|
|
AstNode oldSuccessor = nextSibling; |
|
|
|
|
AstNode? oldSuccessor = nextSibling; |
|
|
|
|
Role oldRole = this.Role; |
|
|
|
|
Remove(); |
|
|
|
|
AstNode replacement = replaceFunction(this); |
|
|
|
|
AstNode? replacement = replaceFunction(this); |
|
|
|
|
if (oldSuccessor != null && oldSuccessor.parent != oldParent) |
|
|
|
|
throw new InvalidOperationException("replace function changed nextSibling of node being replaced?"); |
|
|
|
|
if (!(replacement == null || replacement.IsNull)) |
|
|
|
@ -626,7 +627,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -626,7 +627,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
copy.flags &= ~frozenBit; // unfreeze the copy
|
|
|
|
|
|
|
|
|
|
// Then perform a deep copy:
|
|
|
|
|
for (AstNode cur = firstChild; cur != null; cur = cur.nextSibling) |
|
|
|
|
for (AstNode? cur = firstChild; cur != null; cur = cur.nextSibling) |
|
|
|
|
{ |
|
|
|
|
copy.AddChildUnsafe(cur.Clone(), cur.Role); |
|
|
|
|
} |
|
|
|
@ -649,37 +650,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -649,37 +650,37 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
public abstract S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data); |
|
|
|
|
|
|
|
|
|
#region Pattern Matching
|
|
|
|
|
protected static bool MatchString(string pattern, string text) |
|
|
|
|
protected static bool MatchString(string? pattern, string? text) |
|
|
|
|
{ |
|
|
|
|
return PatternMatching.Pattern.MatchString(pattern, text); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected internal abstract bool DoMatch(AstNode other, PatternMatching.Match match); |
|
|
|
|
protected internal abstract bool DoMatch(AstNode? other, PatternMatching.Match match); |
|
|
|
|
|
|
|
|
|
bool PatternMatching.INode.DoMatch(PatternMatching.INode other, PatternMatching.Match match) |
|
|
|
|
bool PatternMatching.INode.DoMatch(PatternMatching.INode? other, PatternMatching.Match match) |
|
|
|
|
{ |
|
|
|
|
AstNode o = other as AstNode; |
|
|
|
|
AstNode? o = other as AstNode; |
|
|
|
|
// try matching if other is null, or if other is an AstNode
|
|
|
|
|
return (other == null || o != null) && DoMatch(o, match); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) |
|
|
|
|
bool PatternMatching.INode.DoMatchCollection(Role? role, PatternMatching.INode? pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo? backtrackingInfo) |
|
|
|
|
{ |
|
|
|
|
AstNode o = pos as AstNode; |
|
|
|
|
AstNode? o = pos as AstNode; |
|
|
|
|
return (pos == null || o != null) && DoMatch(o, match); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PatternMatching.INode PatternMatching.INode.NextSibling { |
|
|
|
|
PatternMatching.INode? PatternMatching.INode.NextSibling { |
|
|
|
|
get { return nextSibling; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PatternMatching.INode PatternMatching.INode.FirstChild { |
|
|
|
|
PatternMatching.INode? PatternMatching.INode.FirstChild { |
|
|
|
|
get { return firstChild; } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
public AstNode GetNextNode() |
|
|
|
|
public AstNode? GetNextNode() |
|
|
|
|
{ |
|
|
|
|
if (NextSibling != null) |
|
|
|
|
return NextSibling; |
|
|
|
@ -693,7 +694,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -693,7 +694,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The next node.</returns>
|
|
|
|
|
/// <param name="pred">The predicate.</param>
|
|
|
|
|
public AstNode GetNextNode(Func<AstNode, bool> pred) |
|
|
|
|
public AstNode? GetNextNode(Func<AstNode, bool> pred) |
|
|
|
|
{ |
|
|
|
|
var next = GetNextNode(); |
|
|
|
|
while (next != null && !pred(next)) |
|
|
|
@ -701,7 +702,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -701,7 +702,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
return next; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public AstNode GetPrevNode() |
|
|
|
|
public AstNode? GetPrevNode() |
|
|
|
|
{ |
|
|
|
|
if (PrevSibling != null) |
|
|
|
|
return PrevSibling; |
|
|
|
@ -715,7 +716,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -715,7 +716,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The next node.</returns>
|
|
|
|
|
/// <param name="pred">The predicate.</param>
|
|
|
|
|
public AstNode GetPrevNode(Func<AstNode, bool> pred) |
|
|
|
|
public AstNode? GetPrevNode(Func<AstNode, bool> pred) |
|
|
|
|
{ |
|
|
|
|
var prev = GetPrevNode(); |
|
|
|
|
while (prev != null && !pred(prev)) |
|
|
|
@ -723,7 +724,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -723,7 +724,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
return prev; |
|
|
|
|
} |
|
|
|
|
// filters all non c# nodes (comments, white spaces or pre processor directives)
|
|
|
|
|
public AstNode GetCSharpNodeBefore(AstNode node) |
|
|
|
|
public AstNode? GetCSharpNodeBefore(AstNode node) |
|
|
|
|
{ |
|
|
|
|
var n = node.PrevSibling; |
|
|
|
|
while (n != null) |
|
|
|
@ -740,7 +741,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -740,7 +741,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The next node.</returns>
|
|
|
|
|
/// <param name="pred">The predicate.</param>
|
|
|
|
|
public AstNode GetNextSibling(Func<AstNode, bool> pred) |
|
|
|
|
public AstNode? GetNextSibling(Func<AstNode, bool> pred) |
|
|
|
|
{ |
|
|
|
|
var next = NextSibling; |
|
|
|
|
while (next != null && !pred(next)) |
|
|
|
@ -753,7 +754,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -753,7 +754,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns>The next node.</returns>
|
|
|
|
|
/// <param name="pred">The predicate.</param>
|
|
|
|
|
public AstNode GetPrevSibling(Func<AstNode, bool> pred) |
|
|
|
|
public AstNode? GetPrevSibling(Func<AstNode, bool> pred) |
|
|
|
|
{ |
|
|
|
|
var prev = PrevSibling; |
|
|
|
|
while (prev != null && !pred(prev)) |
|
|
|
@ -767,7 +768,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -767,7 +768,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// the current method declaration.
|
|
|
|
|
/// (End exclusive)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public AstNode GetNodeAt(int line, int column, Predicate<AstNode> pred = null) |
|
|
|
|
public AstNode? GetNodeAt(int line, int column, Predicate<AstNode>? pred = null) |
|
|
|
|
{ |
|
|
|
|
return GetNodeAt(new TextLocation(line, column), pred); |
|
|
|
|
} |
|
|
|
@ -777,9 +778,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -777,9 +778,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// the current method declaration.
|
|
|
|
|
/// (End exclusive)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public AstNode GetNodeAt(TextLocation location, Predicate<AstNode> pred = null) |
|
|
|
|
public AstNode? GetNodeAt(TextLocation location, Predicate<AstNode>? pred = null) |
|
|
|
|
{ |
|
|
|
|
AstNode result = null; |
|
|
|
|
AstNode? result = null; |
|
|
|
|
AstNode node = this; |
|
|
|
|
while (node.LastChild != null) |
|
|
|
|
{ |
|
|
|
@ -806,7 +807,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -806,7 +807,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// the current method declaration.
|
|
|
|
|
/// (End exclusive)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public T GetNodeAt<T>(int line, int column) where T : AstNode |
|
|
|
|
public T? GetNodeAt<T>(int line, int column) where T : AstNode |
|
|
|
|
{ |
|
|
|
|
return GetNodeAt<T>(new TextLocation(line, column)); |
|
|
|
|
} |
|
|
|
@ -816,9 +817,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -816,9 +817,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// the current method declaration.
|
|
|
|
|
/// (End exclusive)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public T GetNodeAt<T>(TextLocation location) where T : AstNode |
|
|
|
|
public T? GetNodeAt<T>(TextLocation location) where T : AstNode |
|
|
|
|
{ |
|
|
|
|
T result = null; |
|
|
|
|
T? result = null; |
|
|
|
|
AstNode node = this; |
|
|
|
|
while (node.LastChild != null) |
|
|
|
|
{ |
|
|
|
@ -848,7 +849,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -848,7 +849,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// the current method declaration.
|
|
|
|
|
/// (End inclusive)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public AstNode GetAdjacentNodeAt(int line, int column, Predicate<AstNode> pred = null) |
|
|
|
|
public AstNode? GetAdjacentNodeAt(int line, int column, Predicate<AstNode>? pred = null) |
|
|
|
|
{ |
|
|
|
|
return GetAdjacentNodeAt(new TextLocation(line, column), pred); |
|
|
|
|
} |
|
|
|
@ -858,9 +859,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -858,9 +859,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// the current method declaration.
|
|
|
|
|
/// (End inclusive)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public AstNode GetAdjacentNodeAt(TextLocation location, Predicate<AstNode> pred = null) |
|
|
|
|
public AstNode? GetAdjacentNodeAt(TextLocation location, Predicate<AstNode>? pred = null) |
|
|
|
|
{ |
|
|
|
|
AstNode result = null; |
|
|
|
|
AstNode? result = null; |
|
|
|
|
AstNode node = this; |
|
|
|
|
while (node.LastChild != null) |
|
|
|
|
{ |
|
|
|
@ -887,7 +888,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -887,7 +888,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// the current method declaration.
|
|
|
|
|
/// (End inclusive)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public T GetAdjacentNodeAt<T>(int line, int column) where T : AstNode |
|
|
|
|
public T? GetAdjacentNodeAt<T>(int line, int column) where T : AstNode |
|
|
|
|
{ |
|
|
|
|
return GetAdjacentNodeAt<T>(new TextLocation(line, column)); |
|
|
|
|
} |
|
|
|
@ -897,9 +898,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -897,9 +898,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// the current method declaration.
|
|
|
|
|
/// (End inclusive)
|
|
|
|
|
/// </summary>
|
|
|
|
|
public T GetAdjacentNodeAt<T>(TextLocation location) where T : AstNode |
|
|
|
|
public T? GetAdjacentNodeAt<T>(TextLocation location) where T : AstNode |
|
|
|
|
{ |
|
|
|
|
T result = null; |
|
|
|
|
T? result = null; |
|
|
|
|
AstNode node = this; |
|
|
|
|
while (node.LastChild != null) |
|
|
|
|
{ |
|
|
|
@ -908,8 +909,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -908,8 +909,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
child = child.prevSibling; |
|
|
|
|
if (child != null && location <= child.EndLocation) |
|
|
|
|
{ |
|
|
|
|
if (child is T) |
|
|
|
|
result = (T)child; |
|
|
|
|
if (child is T t) |
|
|
|
|
result = t; |
|
|
|
|
node = child; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
@ -928,7 +929,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -928,7 +929,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// </summary>
|
|
|
|
|
public AstNode GetNodeContaining(TextLocation startLocation, TextLocation endLocation) |
|
|
|
|
{ |
|
|
|
|
for (AstNode child = firstChild; child != null; child = child.nextSibling) |
|
|
|
|
for (AstNode? child = firstChild; child != null; child = child.nextSibling) |
|
|
|
|
{ |
|
|
|
|
if (child.StartLocation <= startLocation && endLocation <= child.EndLocation) |
|
|
|
|
return child.GetNodeContaining(startLocation, endLocation); |
|
|
|
@ -949,10 +950,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -949,10 +950,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// </summary>
|
|
|
|
|
public IEnumerable<AstNode> GetNodesBetween(TextLocation start, TextLocation end) |
|
|
|
|
{ |
|
|
|
|
AstNode node = this; |
|
|
|
|
AstNode? node = this; |
|
|
|
|
while (node != null) |
|
|
|
|
{ |
|
|
|
|
AstNode next; |
|
|
|
|
AstNode? next; |
|
|
|
|
if (start <= node.StartLocation && node.EndLocation <= end) |
|
|
|
|
{ |
|
|
|
|
// Remember next before yielding node.
|
|
|
|
@ -984,7 +985,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
@@ -984,7 +985,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
|
|
|
|
|
/// <param name='formattingOptions'>
|
|
|
|
|
/// Formatting options.
|
|
|
|
|
/// </param>
|
|
|
|
|
public virtual string ToString(CSharpFormattingOptions formattingOptions) |
|
|
|
|
public virtual string ToString(CSharpFormattingOptions? formattingOptions) |
|
|
|
|
{ |
|
|
|
|
if (IsNull) |
|
|
|
|
return ""; |
|
|
|
|