@ -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 "" ;