Browse Source

#nullable enable for AstNode

issue1638
Daniel Grunwald 4 years ago
parent
commit
ffed8ea2c8
  1. 2
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  2. 143
      ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs
  3. 3
      ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs
  4. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs
  5. 8
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs
  6. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs
  7. 3
      ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs
  8. 12
      ICSharpCode.Decompiler/CSharp/Syntax/Role.cs
  9. 14
      ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs
  10. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs
  11. 4
      ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs
  12. 4
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs
  13. 3
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs

2
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -543,7 +543,7 @@ namespace ICSharpCode.Decompiler.CSharp
argumentList.Arguments.ToList(), argumentList.ArgumentNames); argumentList.Arguments.ToList(), argumentList.ArgumentNames);
if (((AssignmentExpression)assignment).Left is IndexerExpression indexer && !indexer.Target.IsNull) if (((AssignmentExpression)assignment).Left is IndexerExpression indexer && !indexer.Target.IsNull)
indexer.Target.ReplaceWith(n => null); indexer.Target.Remove();
if (value != null) if (value != null)
return assignment; return assignment;

143
ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs

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

3
ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs

@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly TokenRole ReadonlyRole = new TokenRole("readonly"); public static readonly TokenRole ReadonlyRole = new TokenRole("readonly");
public static readonly TokenRole NullableRole = new TokenRole("?"); public static readonly TokenRole NullableRole = new TokenRole("?");
public static readonly TokenRole PointerRole = new TokenRole("*"); public static readonly TokenRole PointerRole = new TokenRole("*");
public static readonly Role<ArraySpecifier> ArraySpecifierRole = new Role<ArraySpecifier>("ArraySpecifier"); public static readonly Role<ArraySpecifier> ArraySpecifierRole = new Role<ArraySpecifier>("ArraySpecifier", null);
public AstNodeCollection<AttributeSection> Attributes { public AstNodeCollection<AttributeSection> Attributes {
get { return base.GetChildrenByRole(AttributeRole); } get { return base.GetChildrenByRole(AttributeRole); }
} }
@ -299,4 +299,3 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
} }
} }

2
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class ArrayCreateExpression : Expression public class ArrayCreateExpression : Expression
{ {
public readonly static TokenRole NewKeywordRole = new TokenRole("new"); public readonly static TokenRole NewKeywordRole = new TokenRole("new");
public readonly static Role<ArraySpecifier> AdditionalArraySpecifierRole = new Role<ArraySpecifier>("AdditionalArraySpecifier"); public readonly static Role<ArraySpecifier> AdditionalArraySpecifierRole = new Role<ArraySpecifier>("AdditionalArraySpecifier", null);
public readonly static Role<ArrayInitializerExpression> InitializerRole = new Role<ArrayInitializerExpression>("Initializer", ArrayInitializerExpression.Null); public readonly static Role<ArrayInitializerExpression> InitializerRole = new Role<ArrayInitializerExpression>("Initializer", ArrayInitializerExpression.Null);
public CSharpTokenNode NewToken { public CSharpTokenNode NewToken {

8
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs

@ -16,13 +16,11 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.CSharp.Syntax namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
public class QueryExpression : Expression public class QueryExpression : Expression
{ {
public static readonly Role<QueryClause> ClauseRole = new Role<QueryClause>("Clause"); public static readonly Role<QueryClause> ClauseRole = new Role<QueryClause>("Clause", null);
#region Null #region Null
public new static readonly QueryExpression Null = new NullQueryExpression(); public new static readonly QueryExpression Null = new NullQueryExpression();
@ -420,7 +418,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class QueryOrderClause : QueryClause public class QueryOrderClause : QueryClause
{ {
public static readonly TokenRole OrderbyKeywordRole = new TokenRole("orderby"); public static readonly TokenRole OrderbyKeywordRole = new TokenRole("orderby");
public static readonly Role<QueryOrdering> OrderingRole = new Role<QueryOrdering>("Ordering"); public static readonly Role<QueryOrdering> OrderingRole = new Role<QueryOrdering>("Ordering", null);
public CSharpTokenNode OrderbyToken { public CSharpTokenNode OrderbyToken {
get { return GetChildByRole(OrderbyKeywordRole); } get { return GetChildByRole(OrderbyKeywordRole); }
@ -585,4 +583,4 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return o != null && this.Projection.DoMatch(o.Projection, match) && this.Key.DoMatch(o.Key, match); return o != null && this.Projection.DoMatch(o.Projection, match) && this.Key.DoMatch(o.Key, match);
} }
} }
} }

2
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class SwitchExpression : Expression public class SwitchExpression : Expression
{ {
public static readonly TokenRole SwitchKeywordRole = new TokenRole("switch"); public static readonly TokenRole SwitchKeywordRole = new TokenRole("switch");
public static readonly Role<SwitchExpressionSection> SwitchSectionRole = new Role<SwitchExpressionSection>("SwitchSection"); public static readonly Role<SwitchExpressionSection> SwitchSectionRole = new Role<SwitchExpressionSection>("SwitchSection", null);
public Expression Expression { public Expression Expression {
get { return GetChildByRole(Roles.Expression); } get { return GetChildByRole(Roles.Expression); }

3
ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs

@ -69,7 +69,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class PragmaWarningPreprocessorDirective : PreProcessorDirective public class PragmaWarningPreprocessorDirective : PreProcessorDirective
{ {
public static readonly Role<PrimitiveExpression> WarningRole = new Role<PrimitiveExpression>("Warning"); public static readonly Role<PrimitiveExpression> WarningRole = new Role<PrimitiveExpression>("Warning", null);
public static readonly TokenRole PragmaKeywordRole = new TokenRole("#pragma"); public static readonly TokenRole PragmaKeywordRole = new TokenRole("#pragma");
public static readonly TokenRole WarningKeywordRole = new TokenRole("warning"); public static readonly TokenRole WarningKeywordRole = new TokenRole("warning");
@ -200,4 +200,3 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
} }
} }

12
ICSharpCode.Decompiler/CSharp/Syntax/Role.cs

@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
#nullable enable
using System; using System;
using System.Threading; using System.Threading;
@ -64,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// Represents the role a node plays within its parent. /// Represents the role a node plays within its parent.
/// All nodes with this role have type T. /// All nodes with this role have type T.
/// </summary> /// </summary>
public class Role<T> : Role where T : class public class Role<T> : Role where T : class?
{ {
readonly string name; // helps with debugging the AST readonly string name; // helps with debugging the AST
readonly T nullObject; readonly T nullObject;
@ -86,21 +88,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return node is T; return node is T;
} }
[Obsolete("Use the other overload explicitly specifying the nullObject.")]
public Role(string name) public Role(string name)
{ {
if (name == null) if (name == null)
throw new ArgumentNullException(nameof(name)); throw new ArgumentNullException(nameof(name));
this.name = name; this.name = name;
this.nullObject = null!;
} }
public Role(string name, T nullObject) public Role(string name, T nullObject)
{ {
if (name == null) this.name = name ?? throw new ArgumentNullException(nameof(name));
throw new ArgumentNullException(nameof(name));
if (nullObject == null)
throw new ArgumentNullException(nameof(nullObject));
this.nullObject = nullObject; this.nullObject = nullObject;
this.name = name;
} }
public override string ToString() public override string ToString()

14
ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs

@ -34,18 +34,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
// some pre defined constants for common roles // some pre defined constants for common roles
public static readonly Role<Identifier> Identifier = new Role<Identifier>("Identifier", Syntax.Identifier.Null); public static readonly Role<Identifier> Identifier = new Role<Identifier>("Identifier", Syntax.Identifier.Null);
public static readonly Role<BlockStatement> Body = new Role<BlockStatement>("Body", BlockStatement.Null); public static readonly Role<BlockStatement> Body = new Role<BlockStatement>("Body", BlockStatement.Null);
public static readonly Role<ParameterDeclaration> Parameter = new Role<ParameterDeclaration>("Parameter"); public static readonly Role<ParameterDeclaration> Parameter = new Role<ParameterDeclaration>("Parameter", null);
public static readonly Role<Expression> Argument = new Role<Expression>("Argument", Syntax.Expression.Null); public static readonly Role<Expression> Argument = new Role<Expression>("Argument", Syntax.Expression.Null);
public static readonly Role<AstType> Type = new Role<AstType>("Type", AstType.Null); public static readonly Role<AstType> Type = new Role<AstType>("Type", AstType.Null);
public static readonly Role<Expression> Expression = new Role<Expression>("Expression", Syntax.Expression.Null); public static readonly Role<Expression> Expression = new Role<Expression>("Expression", Syntax.Expression.Null);
public static readonly Role<Expression> TargetExpression = new Role<Expression>("Target", Syntax.Expression.Null); public static readonly Role<Expression> TargetExpression = new Role<Expression>("Target", Syntax.Expression.Null);
public readonly static Role<Expression> Condition = new Role<Expression>("Condition", Syntax.Expression.Null); public readonly static Role<Expression> Condition = new Role<Expression>("Condition", Syntax.Expression.Null);
public static readonly Role<TypeParameterDeclaration> TypeParameter = new Role<TypeParameterDeclaration>("TypeParameter"); public static readonly Role<TypeParameterDeclaration> TypeParameter = new Role<TypeParameterDeclaration>("TypeParameter", null);
public static readonly Role<AstType> TypeArgument = new Role<AstType>("TypeArgument", AstType.Null); public static readonly Role<AstType> TypeArgument = new Role<AstType>("TypeArgument", AstType.Null);
public readonly static Role<Constraint> Constraint = new Role<Constraint>("Constraint"); public readonly static Role<Constraint> Constraint = new Role<Constraint>("Constraint", null);
public static readonly Role<VariableInitializer> Variable = new Role<VariableInitializer>("Variable", VariableInitializer.Null); public static readonly Role<VariableInitializer> Variable = new Role<VariableInitializer>("Variable", VariableInitializer.Null);
public static readonly Role<Statement> EmbeddedStatement = new Role<Statement>("EmbeddedStatement", Statement.Null); public static readonly Role<Statement> EmbeddedStatement = new Role<Statement>("EmbeddedStatement", Statement.Null);
public readonly static Role<EntityDeclaration> TypeMemberRole = new Role<EntityDeclaration>("TypeMember"); public readonly static Role<EntityDeclaration> TypeMemberRole = new Role<EntityDeclaration>("TypeMember", null);
public static readonly Role<VariableDesignation> VariableDesignationRole = new Role<VariableDesignation>("VariableDesignation", VariableDesignation.Null); public static readonly Role<VariableDesignation> VariableDesignationRole = new Role<VariableDesignation>("VariableDesignation", VariableDesignation.Null);
@ -68,12 +68,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly TokenRole Colon = new TokenRole(":"); public static readonly TokenRole Colon = new TokenRole(":");
public static readonly TokenRole DoubleColon = new TokenRole("::"); public static readonly TokenRole DoubleColon = new TokenRole("::");
public static readonly TokenRole Arrow = new TokenRole("=>"); public static readonly TokenRole Arrow = new TokenRole("=>");
public static readonly Role<Comment> Comment = new Role<Comment>("Comment"); public static readonly Role<Comment> Comment = new Role<Comment>("Comment", null);
public static readonly Role<PreProcessorDirective> PreProcessorDirective = new Role<PreProcessorDirective>("PreProcessorDirective"); public static readonly Role<PreProcessorDirective> PreProcessorDirective = new Role<PreProcessorDirective>("PreProcessorDirective", null);
public readonly static Role<AstType> BaseType = new Role<AstType>("BaseType", AstType.Null); public readonly static Role<AstType> BaseType = new Role<AstType>("BaseType", AstType.Null);
public static readonly Role<Attribute> Attribute = new Role<Attribute>("Attribute"); public static readonly Role<Attribute> Attribute = new Role<Attribute>("Attribute", null);
public static readonly Role<CSharpTokenNode> AttributeTargetRole = new Role<CSharpTokenNode>("AttributeTarget", CSharpTokenNode.Null); public static readonly Role<CSharpTokenNode> AttributeTargetRole = new Role<CSharpTokenNode>("AttributeTarget", CSharpTokenNode.Null);
public readonly static TokenRole WhereKeyword = new TokenRole("where"); public readonly static TokenRole WhereKeyword = new TokenRole("where");

2
ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs

@ -22,7 +22,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
public class LocalFunctionDeclarationStatement : Statement public class LocalFunctionDeclarationStatement : Statement
{ {
public static readonly Role<MethodDeclaration> MethodDeclarationRole = new Role<MethodDeclaration>("Method"); public static readonly Role<MethodDeclaration> MethodDeclarationRole = new Role<MethodDeclaration>("Method", null);
public MethodDeclaration Declaration { public MethodDeclaration Declaration {
get { return GetChildByRole(MethodDeclarationRole); } get { return GetChildByRole(MethodDeclarationRole); }

4
ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class SwitchStatement : Statement public class SwitchStatement : Statement
{ {
public static readonly TokenRole SwitchKeywordRole = new TokenRole("switch"); public static readonly TokenRole SwitchKeywordRole = new TokenRole("switch");
public static readonly Role<SwitchSection> SwitchSectionRole = new Role<SwitchSection>("SwitchSection"); public static readonly Role<SwitchSection> SwitchSectionRole = new Role<SwitchSection>("SwitchSection", null);
public CSharpTokenNode SwitchToken { public CSharpTokenNode SwitchToken {
get { return GetChildByRole(SwitchKeywordRole); } get { return GetChildByRole(SwitchKeywordRole); }
@ -134,7 +134,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
#endregion #endregion
public static readonly Role<CaseLabel> CaseLabelRole = new Role<CaseLabel>("CaseLabel"); public static readonly Role<CaseLabel> CaseLabelRole = new Role<CaseLabel>("CaseLabel", null);
public override NodeType NodeType { public override NodeType NodeType {
get { get {

4
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs

@ -25,8 +25,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
public abstract class EntityDeclaration : AstNode public abstract class EntityDeclaration : AstNode
{ {
public static readonly Role<AttributeSection> AttributeRole = new Role<AttributeSection>("Attribute"); public static readonly Role<AttributeSection> AttributeRole = new Role<AttributeSection>("Attribute", null);
public static readonly Role<CSharpModifierToken> ModifierRole = new Role<CSharpModifierToken>("Modifier"); public static readonly Role<CSharpModifierToken> ModifierRole = new Role<CSharpModifierToken>("Modifier", null);
public static readonly Role<AstType> PrivateImplementationTypeRole = new Role<AstType>("PrivateImplementationType", AstType.Null); public static readonly Role<AstType> PrivateImplementationTypeRole = new Role<AstType>("PrivateImplementationType", AstType.Null);
public override NodeType NodeType { public override NodeType NodeType {

3
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class FixedFieldDeclaration : EntityDeclaration public class FixedFieldDeclaration : EntityDeclaration
{ {
public static readonly TokenRole FixedKeywordRole = new TokenRole("fixed"); public static readonly TokenRole FixedKeywordRole = new TokenRole("fixed");
public static readonly Role<FixedVariableInitializer> VariableRole = new Role<FixedVariableInitializer>("FixedVariable"); public static readonly Role<FixedVariableInitializer> VariableRole = new Role<FixedVariableInitializer>("FixedVariable", null);
public override SymbolKind SymbolKind { public override SymbolKind SymbolKind {
get { return SymbolKind.Field; } get { return SymbolKind.Field; }
@ -67,4 +67,3 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
} }
} }

Loading…
Cancel
Save