Browse Source

Merge branch 'nullable'

issue1638
Daniel Grunwald 4 years ago
parent
commit
544d9bb217
  1. 2
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  2. 4
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs
  3. 143
      ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs
  4. 3
      ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs
  5. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs
  6. 8
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs
  7. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs
  8. 3
      ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs
  9. 12
      ICSharpCode.Decompiler/CSharp/Syntax/Role.cs
  10. 14
      ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs
  11. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs
  12. 4
      ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs
  13. 4
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs
  14. 3
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs
  15. 7
      ICSharpCode.Decompiler/IL/ILAstWritingOptions.cs
  16. 5
      ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs
  17. 7
      ICSharpCode.Decompiler/IL/ILTypeExtensions.cs
  18. 20
      ICSharpCode.Decompiler/IL/ILVariable.cs
  19. 3
      ICSharpCode.Decompiler/IL/InstructionFlags.cs
  20. 3
      ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
  21. 508
      ICSharpCode.Decompiler/IL/Instructions.cs
  22. 85
      ICSharpCode.Decompiler/IL/Instructions.tt
  23. 7
      ICSharpCode.Decompiler/IL/Instructions/Await.cs
  24. 5
      ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
  25. 47
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  26. 32
      ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs
  27. 25
      ICSharpCode.Decompiler/IL/Instructions/Branch.cs
  28. 5
      ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs
  29. 15
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  30. 6
      ICSharpCode.Decompiler/IL/Instructions/Comp.cs
  31. 5
      ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs
  32. 3
      ICSharpCode.Decompiler/IL/Instructions/Conv.cs
  33. 13
      ICSharpCode.Decompiler/IL/Instructions/DeconstructResultInstruction.cs
  34. 3
      ICSharpCode.Decompiler/IL/Instructions/DefaultValue.cs
  35. 43
      ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs
  36. 7
      ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs
  37. 39
      ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs
  38. 22
      ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs
  39. 5
      ICSharpCode.Decompiler/IL/Instructions/ILVariableCollection.cs
  40. 9
      ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs
  41. 3
      ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs
  42. 3
      ICSharpCode.Decompiler/IL/Instructions/LdLen.cs
  43. 13
      ICSharpCode.Decompiler/IL/Instructions/Leave.cs
  44. 3
      ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs
  45. 3
      ICSharpCode.Decompiler/IL/Instructions/LogicInstructions.cs
  46. 30
      ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs
  47. 3
      ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs
  48. 3
      ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs
  49. 3
      ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs
  50. 75
      ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
  51. 13
      ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs
  52. 7
      ICSharpCode.Decompiler/IL/Instructions/StLoc.cs
  53. 13
      ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs
  54. 4
      ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs
  55. 11
      ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs
  56. 3
      ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs
  57. 3
      ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs
  58. 16
      ICSharpCode.Decompiler/IL/Patterns/AnyNode.cs
  59. 13
      ICSharpCode.Decompiler/IL/Patterns/ListMatch.cs
  60. 5
      ICSharpCode.Decompiler/IL/Patterns/Match.cs
  61. 3
      ICSharpCode.Decompiler/IL/PrimitiveType.cs
  62. 4
      ICSharpCode.Decompiler/IL/SemanticHelper.cs
  63. 1
      ICSharpCode.Decompiler/IL/SlotInfo.cs
  64. 1
      ICSharpCode.Decompiler/IL/StackType.cs
  65. 3
      ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs
  66. 3
      ICSharpCode.Decompiler/IL/Transforms/FixRemainingIncrements.cs
  67. 17
      ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs
  68. 8
      ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs
  69. 2
      ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs
  70. 6
      ICSharpCode.Decompiler/TypeSystem/IMember.cs
  71. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs
  72. 1
      ICSharpCode.Decompiler/Util/BitSet.cs
  73. 13
      ICSharpCode.Decompiler/Util/BusyManager.cs
  74. 2
      ICSharpCode.Decompiler/Util/CacheManager.cs
  75. 6
      ICSharpCode.Decompiler/Util/CallbackOnDispose.cs
  76. 35
      ICSharpCode.Decompiler/Util/CollectionExtensions.cs
  77. 5
      ICSharpCode.Decompiler/Util/EmptyList.cs
  78. 5
      ICSharpCode.Decompiler/Util/ExtensionMethods.cs
  79. 24
      ICSharpCode.Decompiler/Util/FileUtility.cs
  80. 26
      ICSharpCode.Decompiler/Util/GraphVizGraph.cs
  81. 7
      ICSharpCode.Decompiler/Util/Interval.cs
  82. 3
      ICSharpCode.Decompiler/Util/KeyComparer.cs
  83. 7
      ICSharpCode.Decompiler/Util/LongSet.cs
  84. 5
      ICSharpCode.Decompiler/Util/MultiDictionary.cs
  85. 8
      ICSharpCode.Decompiler/Util/NullAttributes.cs
  86. 3
      ICSharpCode.Decompiler/Util/Platform.cs
  87. 15
      ICSharpCode.Decompiler/Util/ProjectedList.cs
  88. 7
      ICSharpCode.Decompiler/Util/ReferenceComparer.cs
  89. 27
      ICSharpCode.Decompiler/Util/ResourcesFile.cs
  90. 15
      ICSharpCode.Decompiler/Util/TreeTraversal.cs
  91. 7
      ICSharpCode.Decompiler/Util/UnicodeNewline.cs
  92. 14
      ICSharpCode.Decompiler/Util/UnionFind.cs
  93. 23
      ICSharpCode.Decompiler/Util/Win32Resources.cs
  94. 4
      ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj

2
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

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

4
ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs

@ -128,9 +128,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver @@ -128,9 +128,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return null; }
}
IType IEntity.DeclaringType {
get { return null; }
}
public IType DeclaringType => SpecialType.UnknownType;
IMember IMember.MemberDefinition {
get { return this; }

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

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

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

@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly TokenRole ReadonlyRole = new TokenRole("readonly");
public static readonly TokenRole NullableRole = 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 {
get { return base.GetChildrenByRole(AttributeRole); }
}
@ -299,4 +299,3 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -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 @@ -25,7 +25,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class ArrayCreateExpression : Expression
{
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 CSharpTokenNode NewToken {

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

@ -16,13 +16,11 @@ @@ -16,13 +16,11 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
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
public new static readonly QueryExpression Null = new NullQueryExpression();
@ -420,7 +418,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -420,7 +418,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class QueryOrderClause : QueryClause
{
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 {
get { return GetChildByRole(OrderbyKeywordRole); }
@ -585,4 +583,4 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -585,4 +583,4 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
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 @@ -25,7 +25,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class SwitchExpression : Expression
{
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 {
get { return GetChildByRole(Roles.Expression); }

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

@ -69,7 +69,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -69,7 +69,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
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 WarningKeywordRole = new TokenRole("warning");
@ -200,4 +200,3 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -200,4 +200,3 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
}

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

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

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

@ -34,18 +34,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -34,18 +34,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
// some pre defined constants for common roles
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<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<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> TargetExpression = new Role<Expression>("Target", 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 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<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);
@ -68,12 +68,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -68,12 +68,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly TokenRole Colon = new TokenRole(":");
public static readonly TokenRole DoubleColon = new TokenRole("::");
public static readonly TokenRole Arrow = new TokenRole("=>");
public static readonly Role<Comment> Comment = new Role<Comment>("Comment");
public static readonly Role<PreProcessorDirective> PreProcessorDirective = new Role<PreProcessorDirective>("PreProcessorDirective");
public static readonly Role<Comment> Comment = new Role<Comment>("Comment", null);
public static readonly Role<PreProcessorDirective> PreProcessorDirective = new Role<PreProcessorDirective>("PreProcessorDirective", 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 readonly static TokenRole WhereKeyword = new TokenRole("where");

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

@ -22,7 +22,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -22,7 +22,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
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 {
get { return GetChildByRole(MethodDeclarationRole); }

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

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class SwitchStatement : Statement
{
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 {
get { return GetChildByRole(SwitchKeywordRole); }
@ -134,7 +134,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -134,7 +134,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
#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 {
get {

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

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

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

@ -30,7 +30,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -30,7 +30,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public class FixedFieldDeclaration : EntityDeclaration
{
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 {
get { return SymbolKind.Field; }
@ -67,4 +67,3 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -67,4 +67,3 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
}

7
ICSharpCode.Decompiler/IL/ILAstWritingOptions.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2017 Daniel Grunwald
#nullable enable
// Copyright (c) 2017 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -84,7 +85,7 @@ namespace ICSharpCode.Decompiler.IL @@ -84,7 +85,7 @@ namespace ICSharpCode.Decompiler.IL
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
@ -94,6 +95,6 @@ namespace ICSharpCode.Decompiler.IL @@ -94,6 +95,6 @@ namespace ICSharpCode.Decompiler.IL
PropertyChanged?.Invoke(this, e);
}
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangedEventHandler? PropertyChanged;
}
}

5
ICSharpCode.Decompiler/IL/ILInstructionExtensions.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System;
#nullable enable
using System;
using System.Collections.Generic;
using System.Text;
@ -20,7 +21,7 @@ namespace ICSharpCode.Decompiler.IL @@ -20,7 +21,7 @@ namespace ICSharpCode.Decompiler.IL
return target;
}
public static ILInstruction GetNextSibling(this ILInstruction instruction)
public static ILInstruction? GetNextSibling(this ILInstruction? instruction)
{
if (instruction?.Parent == null)
return null;

7
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -145,12 +146,12 @@ namespace ICSharpCode.Decompiler.IL @@ -145,12 +146,12 @@ namespace ICSharpCode.Decompiler.IL
///
/// Returns SpecialType.UnknownType for unsupported instructions.
/// </summary>
public static IType InferType(this ILInstruction inst, ICompilation compilation)
public static IType InferType(this ILInstruction inst, ICompilation? compilation)
{
switch (inst)
{
case NewObj newObj:
return newObj.Method.DeclaringType;
return newObj.Method.DeclaringType ?? SpecialType.UnknownType;
case NewArr newArr:
if (compilation != null)
return new ArrayType(compilation, newArr.Type, newArr.Indices.Count);

20
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -19,7 +20,6 @@ @@ -19,7 +20,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -192,7 +192,7 @@ namespace ICSharpCode.Decompiler.IL @@ -192,7 +192,7 @@ namespace ICSharpCode.Decompiler.IL
}
}
public string Name { get; set; }
public string? Name { get; set; }
public bool HasGeneratedName { get; set; }
@ -202,7 +202,7 @@ namespace ICSharpCode.Decompiler.IL @@ -202,7 +202,7 @@ namespace ICSharpCode.Decompiler.IL
/// <remarks>
/// This property is set automatically when the variable is added to the <c>ILFunction.Variables</c> collection.
/// </remarks>
public ILFunction Function { get; internal set; }
public ILFunction? Function { get; internal set; }
/// <summary>
/// Gets the block container in which this variable is captured.
@ -212,7 +212,7 @@ namespace ICSharpCode.Decompiler.IL @@ -212,7 +212,7 @@ namespace ICSharpCode.Decompiler.IL
/// <remarks>
/// This property returns null for variables that are not captured.
/// </remarks>
public BlockContainer CaptureScope { get; internal set; }
public BlockContainer? CaptureScope { get; internal set; }
/// <summary>
/// Gets the index of this variable within the <c>Function.Variables</c> collection.
@ -309,7 +309,7 @@ namespace ICSharpCode.Decompiler.IL @@ -309,7 +309,7 @@ namespace ICSharpCode.Decompiler.IL
return list.Count - 1;
}
void RemoveInstruction<T>(List<T> list, int index, T inst) where T : class, IInstructionWithVariableOperand
void RemoveInstruction<T>(List<T> list, int index, T? inst) where T : class, IInstructionWithVariableOperand
{
Debug.Assert(list[index] == inst);
int indexToMove = list.Count - 1;
@ -370,7 +370,7 @@ namespace ICSharpCode.Decompiler.IL @@ -370,7 +370,7 @@ namespace ICSharpCode.Decompiler.IL
/// The field which was converted to a local variable.
/// Set when the variable is from a 'yield return' or 'async' state machine.
/// </summary>
public IField StateMachineField;
public IField? StateMachineField;
public ILVariable(VariableKind kind, IType type, int? index = null)
{
@ -398,7 +398,7 @@ namespace ICSharpCode.Decompiler.IL @@ -398,7 +398,7 @@ namespace ICSharpCode.Decompiler.IL
CheckInvariant();
}
public override string ToString()
public override string? ToString()
{
return Name;
}
@ -472,7 +472,7 @@ namespace ICSharpCode.Decompiler.IL @@ -472,7 +472,7 @@ namespace ICSharpCode.Decompiler.IL
if (CaptureScope != null)
{
output.Write(" captured in ");
output.WriteLocalReference(CaptureScope.EntryPoint.Label, CaptureScope);
output.WriteLocalReference(CaptureScope.EntryPoint?.Label, CaptureScope);
}
if (StateMachineField != null)
{
@ -528,7 +528,7 @@ namespace ICSharpCode.Decompiler.IL @@ -528,7 +528,7 @@ namespace ICSharpCode.Decompiler.IL
{
public static readonly ILVariableEqualityComparer Instance = new ILVariableEqualityComparer();
public bool Equals(ILVariable x, ILVariable y)
public bool Equals(ILVariable? x, ILVariable? y)
{
if (x == y)
return true;

3
ICSharpCode.Decompiler/IL/InstructionFlags.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

3
ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

508
ICSharpCode.Decompiler/IL/Instructions.cs

File diff suppressed because it is too large Load Diff

85
ICSharpCode.Decompiler/IL/Instructions.tt

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
@ -32,7 +34,7 @@ @@ -32,7 +34,7 @@
AbstractBaseClass, CustomArguments(("left", null), ("right", null)), HasFlag("InstructionFlags.None")),
new OpCode("CallInstruction", "Instruction with a list of arguments.",
AbstractBaseClass, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}),
CustomWriteTo, MayThrow, SideEffect),
CustomConstructor, CustomWriteTo, MayThrow, SideEffect),
new OpCode("PatternInstruction", "Base class for pattern matching in ILAst.", AbstractBaseClass, ResultType("Unknown")) { Namespace = "ICSharpCode.Decompiler.IL.Patterns" },
new OpCode("CompoundAssignmentInstruction", "Common instruction for compound assignments.",
AbstractBaseClass, CustomConstructor, CustomArguments(("target", null), ("value", null))),
@ -68,7 +70,7 @@ @@ -68,7 +70,7 @@
new ChildInfo("init") { CanInlineInto = true },
new ChildInfo("body")
}),
CustomInvariant("Debug.Assert(Variable.Kind == VariableKind.PinnedRegionLocal);")),
CustomInvariant("DebugAssert(Variable.Kind == VariableKind.PinnedRegionLocal);")),
new OpCode("binary", "Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr.",
CustomClassName("BinaryNumericInstruction"), Binary, CustomWriteTo, CustomConstructor, CustomComputeFlags,
MatchCondition("CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator && IsLifted == o.IsLifted")),
@ -215,11 +217,11 @@ @@ -215,11 +217,11 @@
new OpCode("ldnull", "Loads the null reference.",
CustomClassName("LdNull"), NoArguments, ResultType("O")),
new OpCode("ldftn", "Load method pointer",
CustomClassName("LdFtn"), NoArguments, HasMethodOperand, ResultType("I")),
CustomClassName("LdFtn"), NoArguments, HasMethodOperand(), ResultType("I")),
new OpCode("ldvirtftn", "Load method pointer",
CustomClassName("LdVirtFtn"), Unary, HasMethodOperand, MayThrow, ResultType("I")),
CustomClassName("LdVirtFtn"), Unary, HasMethodOperand(), MayThrow, ResultType("I")),
new OpCode("ldvirtdelegate", "Virtual delegate construction",
CustomClassName("LdVirtDelegate"), Unary, HasTypeOperand, HasMethodOperand,
CustomClassName("LdVirtDelegate"), Unary, HasTypeOperand, HasMethodOperand(),
MayThrow, ResultType("O")),
new OpCode("ldtypetoken", "Loads runtime representation of metadata token",
CustomClassName("LdTypeToken"), NoArguments, HasTypeOperand, ResultType("O")),
@ -287,7 +289,7 @@ @@ -287,7 +289,7 @@
+ "The input must be an object reference (O)." + Environment.NewLine
+ "If the input is an array/string, evaluates to a reference to the first element/character, or to a null reference if the array is null or empty." + Environment.NewLine
+ "Otherwise, uses the GetPinnableReference method to get the reference, or evaluates to a null reference if the input is null." + Environment.NewLine,
CustomArguments(("argument", new[] { "O" })), ResultType("Ref"), HasMethodOperand),
CustomArguments(("argument", new[] { "O" })), ResultType("Ref"), HasMethodOperand(nullable: true)),
new OpCode("string.to.int", "Maps a string value to an integer. This is used in switch(string).",
CustomArguments(("argument", new[] { "O" })), CustomConstructor, CustomWriteTo, ResultType("I4")),
@ -297,7 +299,7 @@ @@ -297,7 +299,7 @@
new OpCode("user.logic.operator", "Use of user-defined &amp;&amp; or || operator.",
CustomClassName("UserDefinedLogicOperator"),
HasMethodOperand, ResultType("O"),
HasMethodOperand(), ResultType("O"),
CustomChildren(new []{
new ChildInfo("left") { CanInlineInto = true },
new ChildInfo("right") { CanInlineInto = false } // only executed depending on value of left
@ -337,7 +339,7 @@ @@ -337,7 +339,7 @@
CustomClassName("DynamicIsEventInstruction"), Dynamic, CustomArguments(("argument", new[] { "O" })), CustomWriteTo),
new OpCode("match", "ILAst representation of C# patterns",
CustomClassName("MatchInstruction"), HasVariableOperand("Store"), HasMethodOperand,
CustomClassName("MatchInstruction"), HasVariableOperand("Store"), HasMethodOperand(nullable: true),
BoolFlag("IsDeconstructCall"), BoolFlag("IsDeconstructTuple"), BoolFlag("CheckType"), BoolFlag("CheckNotNull"),
CustomChildren(new []{
new ChildInfo("testedOperand") { CanInlineInto = true },
@ -371,8 +373,8 @@ @@ -371,8 +373,8 @@
};
#>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
@ -437,7 +439,7 @@ namespace <#=opCode.Namespace#> @@ -437,7 +439,7 @@ namespace <#=opCode.Namespace#>
}
<# } #>
<# if (opCode.GeneratePerformMatch) { #>
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
protected internal override bool PerformMatch(ILInstruction? other, ref Patterns.Match match)
{
var o = other as <#=opCode.Name#>;
return <#=string.Join(" && ", opCode.PerformMatchConditions)#>;
@ -637,10 +639,15 @@ namespace ICSharpCode.Decompiler.IL @@ -637,10 +639,15 @@ namespace ICSharpCode.Decompiler.IL
public string TypeName;
public string Name;
public string FieldName;
public bool IsReferenceType = true;
public override string ToString()
{
return "out " + TypeName + " " + Name;
if (IsReferenceType) {
return "[NotNullWhen(true)] out " + TypeName + "? " + Name;
} else {
return "out " + TypeName + " " + Name;
}
}
}
@ -866,7 +873,7 @@ namespace ICSharpCode.Decompiler.IL @@ -866,7 +873,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.WriteArguments.Add("output.Write(\", \");");
opCode.WriteArguments.Add("this." + arg + ".WriteTo(output, options);");
opCode.Members.Add("public static readonly SlotInfo " + children[i].SlotName + " = " + children[i].GetSlotInit() + ";");
opCode.Members.Add("ILInstruction " + arg + ";");
opCode.Members.Add("ILInstruction " + arg + " = null!;");
opCode.Members.Add("public ILInstruction " + argProp + " {" + Environment.NewLine
+ "\tget { return this." + arg + "; }" + Environment.NewLine
+ "\tset {" + Environment.NewLine
@ -885,7 +892,7 @@ namespace ICSharpCode.Decompiler.IL @@ -885,7 +892,7 @@ namespace ICSharpCode.Decompiler.IL
checkString += " || ";
checkString += arg + ".ResultType == " + expectedTypeCode;
}
opCode.Invariants.Add("Debug.Assert(" + checkString + ");");
opCode.Invariants.Add("DebugAssert(" + checkString + ");");
}
}
opCode.WriteArguments.Add("output.Write(')');");
@ -1008,8 +1015,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1008,8 +1015,7 @@ namespace ICSharpCode.Decompiler.IL
Action<OpCode> action = opCode => {
opCode.ConstructorParameters.Add("ILVariable variable");
opCode.Members.Add("ILVariable variable;");
opCode.ConstructorBody.Add("Debug.Assert(variable != null);");
opCode.ConstructorBody.Add("this.variable = variable;");
opCode.ConstructorBody.Add("this.variable = variable ?? throw new ArgumentNullException(nameof(variable));");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "ILVariable", Name = "variable", FieldName = "Variable" });
opCode.PerformMatchConditions.Add("variable == o.variable");
opCode.GenerateWriteTo = true;
@ -1019,7 +1025,7 @@ namespace ICSharpCode.Decompiler.IL @@ -1019,7 +1025,7 @@ namespace ICSharpCode.Decompiler.IL
opCode.Members.Add(@"public ILVariable Variable {
get { return variable; }
set {
Debug.Assert(value != null);
DebugAssert(value != null);
if (IsConnected)
variable.RemoveAccessInstruction(this);
variable = value;
@ -1048,8 +1054,8 @@ protected override void Disconnected() @@ -1048,8 +1054,8 @@ protected override void Disconnected()
}
".Replace("Access", accessType));
if (generateCheckInvariant) {
opCode.Invariants.Add("Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function));");
opCode.Invariants.Add("Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable);");
opCode.Invariants.Add("DebugAssert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function!));");
opCode.Invariants.Add("DebugAssert(phase <= ILPhase.InILReader || variable.Function!.Variables[variable.IndexInFunction] == variable);");
}
};
if (accessType == "Load") {
@ -1093,22 +1099,26 @@ protected override void Disconnected() @@ -1093,22 +1099,26 @@ protected override void Disconnected()
opCode.WriteOperand.Add("type.WriteTo(output);");
};
static Action<OpCode> HasMethodOperand = opCode => {
opCode.ConstructorParameters.Add("IMethod method");
opCode.Members.Add("readonly IMethod method;");
opCode.ConstructorBody.Add("this.method = method;");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = "IMethod", Name = "method", FieldName = "Method" });
opCode.PerformMatchConditions.Add("object.Equals(method, o.method)");
opCode.Members.Add("/// <summary>Returns the method operand.</summary>" + Environment.NewLine
+ "public IMethod Method { get { return method; } }");
opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("if (method != null) {");
opCode.WriteOperand.Add("\toutput.Write(' ');");
opCode.WriteOperand.Add("\tmethod.WriteTo(output);");
opCode.WriteOperand.Add("}");
opCode.Interfaces.Add("IInstructionWithMethodOperand");
};
static Action<OpCode> HasMethodOperand(bool nullable = false)
{
return opCode => {
string n = nullable ? "?" : "";
opCode.ConstructorParameters.Add($"IMethod{n} method");
opCode.Members.Add($"readonly IMethod{n} method;");
opCode.ConstructorBody.Add("this.method = method;");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = $"IMethod{n}", Name = "method", FieldName = "Method", IsReferenceType = !nullable });
opCode.PerformMatchConditions.Add("object.Equals(method, o.method)");
opCode.Members.Add("/// <summary>Returns the method operand.</summary>" + Environment.NewLine
+ $"public IMethod{n} Method => method;");
opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("if (method != null) {");
opCode.WriteOperand.Add("\toutput.Write(' ');");
opCode.WriteOperand.Add("\tmethod.WriteTo(output);");
opCode.WriteOperand.Add("}");
opCode.Interfaces.Add("IInstructionWithMethodOperand");
};
}
static Action<OpCode> HasMemberOperand = opCode => {
opCode.ConstructorParameters.Add("IMember member");
opCode.Members.Add("readonly IMember member;");
@ -1139,7 +1149,12 @@ protected override void Disconnected() @@ -1139,7 +1149,12 @@ protected override void Disconnected()
return opCode => {
NoArguments(opCode);
opCode.ConstructorParameters.Add(operandType + " value");
opCode.MatchParameters.Add(new MatchParamInfo { TypeName = operandType, Name = "value", FieldName = "Value" });
opCode.MatchParameters.Add(new MatchParamInfo {
TypeName = operandType,
Name = "value",
FieldName = "Value",
IsReferenceType = operandType == "string"
});
opCode.PerformMatchConditions.Add("this.Value == o.Value");
opCode.Members.Add("public readonly " + operandType + " Value;");
opCode.ConstructorBody.Add("this.Value = value;");

7
ICSharpCode.Decompiler/IL/Instructions/Await.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2017 Daniel Grunwald
#nullable enable
// Copyright (c) 2017 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -22,7 +23,7 @@ namespace ICSharpCode.Decompiler.IL @@ -22,7 +23,7 @@ namespace ICSharpCode.Decompiler.IL
{
partial class Await
{
public IMethod GetAwaiterMethod;
public IMethod GetResultMethod;
public IMethod? GetAwaiterMethod;
public IMethod? GetResultMethod;
}
}

5
ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -214,5 +215,3 @@ namespace ICSharpCode.Decompiler.IL @@ -214,5 +215,3 @@ namespace ICSharpCode.Decompiler.IL
}
}
}

47
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014-2016 Daniel Grunwald
#nullable enable
// Copyright (c) 2014-2016 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -16,14 +17,13 @@ @@ -16,14 +17,13 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL
{
/// <summary>
@ -48,7 +48,7 @@ namespace ICSharpCode.Decompiler.IL @@ -48,7 +48,7 @@ namespace ICSharpCode.Decompiler.IL
public readonly BlockKind Kind;
public readonly InstructionCollection<ILInstruction> Instructions;
ILInstruction finalInstruction;
ILInstruction finalInstruction = null!;
/// <summary>
/// For blocks in a block container, this field holds
@ -124,10 +124,10 @@ namespace ICSharpCode.Decompiler.IL @@ -124,10 +124,10 @@ namespace ICSharpCode.Decompiler.IL
foreach (var inst in Instructions)
{
var stloc = inst as StLoc;
Debug.Assert(stloc != null, "Instructions in CallWithNamedArgs must be assignments");
Debug.Assert(stloc.Variable.Kind == VariableKind.NamedArgument);
Debug.Assert(stloc.Variable.IsSingleDefinition && stloc.Variable.LoadCount == 1);
Debug.Assert(stloc.Variable.LoadInstructions.Single().Parent == finalInstruction);
DebugAssert(stloc != null, "Instructions in CallWithNamedArgs must be assignments");
DebugAssert(stloc.Variable.Kind == VariableKind.NamedArgument);
DebugAssert(stloc.Variable.IsSingleDefinition && stloc.Variable.LoadCount == 1);
DebugAssert(stloc.Variable.LoadInstructions.Single().Parent == finalInstruction);
}
var call = (CallInstruction)finalInstruction;
if (call.IsInstanceCall)
@ -140,22 +140,22 @@ namespace ICSharpCode.Decompiler.IL @@ -140,22 +140,22 @@ namespace ICSharpCode.Decompiler.IL
case BlockKind.ArrayInitializer:
var final = finalInstruction as LdLoc;
Debug.Assert(final != null && final.Variable.IsSingleDefinition && final.Variable.Kind == VariableKind.InitializerTarget);
IType type = null;
Debug.Assert(Instructions[0].MatchStLoc(final.Variable, out var init) && init.MatchNewArr(out type));
IType? type = null;
Debug.Assert(Instructions[0].MatchStLoc(final!.Variable, out var init) && init.MatchNewArr(out type));
for (int i = 1; i < Instructions.Count; i++)
{
Debug.Assert(Instructions[i].MatchStObj(out ILInstruction target, out _, out var t) && type != null && type.Equals(t));
Debug.Assert(target.MatchLdElema(out t, out ILInstruction array) && type.Equals(t));
Debug.Assert(array.MatchLdLoc(out ILVariable v) && v == final.Variable);
DebugAssert(Instructions[i].MatchStObj(out ILInstruction? target, out _, out var t) && type != null && type.Equals(t));
DebugAssert(target.MatchLdElema(out t, out ILInstruction? array) && type.Equals(t));
DebugAssert(array.MatchLdLoc(out ILVariable? v) && v == final.Variable);
}
break;
case BlockKind.CollectionInitializer:
case BlockKind.ObjectInitializer:
var final2 = finalInstruction as LdLoc;
Debug.Assert(final2 != null);
var initVar2 = final2.Variable;
var initVar2 = final2!.Variable;
Debug.Assert(initVar2.StoreCount == 1 && initVar2.Kind == VariableKind.InitializerTarget);
IType type2 = null;
IType? type2 = null;
bool condition = Instructions[0].MatchStLoc(final2.Variable, out var init2);
Debug.Assert(condition);
Debug.Assert(init2 is NewObj
@ -300,7 +300,7 @@ namespace ICSharpCode.Decompiler.IL @@ -300,7 +300,7 @@ namespace ICSharpCode.Decompiler.IL
public void Remove()
{
Debug.Assert(ChildIndex > 0);
var container = (BlockContainer)Parent;
var container = (BlockContainer)Parent!;
Debug.Assert(container.Blocks[ChildIndex] == this);
container.Blocks.SwapRemoveAt(ChildIndex);
}
@ -325,7 +325,7 @@ namespace ICSharpCode.Decompiler.IL @@ -325,7 +325,7 @@ namespace ICSharpCode.Decompiler.IL
/// Gets the predecessor of the given instruction.
/// Returns null if inst.Parent is not a block.
/// </summary>
public static ILInstruction GetPredecessor(ILInstruction inst)
public static ILInstruction? GetPredecessor(ILInstruction inst)
{
if (inst.Parent is Block block && inst.ChildIndex > 0)
{
@ -341,7 +341,8 @@ namespace ICSharpCode.Decompiler.IL @@ -341,7 +341,8 @@ namespace ICSharpCode.Decompiler.IL
/// If inst is a block consisting of a single instruction, returns that instruction.
/// Otherwise, returns the input instruction.
/// </summary>
public static ILInstruction Unwrap(ILInstruction inst)
[return: NotNullIfNotNull("inst")]
public static ILInstruction? Unwrap(ILInstruction? inst)
{
if (inst is Block block)
{
@ -355,19 +356,19 @@ namespace ICSharpCode.Decompiler.IL @@ -355,19 +356,19 @@ namespace ICSharpCode.Decompiler.IL
/// Gets the closest parent Block.
/// Returns null, if the instruction is not a descendant of a Block.
/// </summary>
public static Block FindClosestBlock(ILInstruction inst)
public static Block? FindClosestBlock(ILInstruction? inst)
{
var curr = inst;
while (curr != null)
{
if (curr is Block)
return (Block)curr;
if (curr is Block b)
return b;
curr = curr.Parent;
}
return null;
}
public bool MatchInlineAssignBlock(out CallInstruction call, out ILInstruction value)
public bool MatchInlineAssignBlock([NotNullWhen(true)] out CallInstruction? call, [NotNullWhen(true)] out ILInstruction? value)
{
call = null;
value = null;
@ -385,7 +386,7 @@ namespace ICSharpCode.Decompiler.IL @@ -385,7 +386,7 @@ namespace ICSharpCode.Decompiler.IL
return this.FinalInstruction.MatchLdLoc(tmp);
}
public bool MatchIfAtEndOfBlock(out ILInstruction condition, out ILInstruction trueInst, out ILInstruction falseInst)
public bool MatchIfAtEndOfBlock([NotNullWhen(true)] out ILInstruction? condition, [NotNullWhen(true)] out ILInstruction? trueInst, [NotNullWhen(true)] out ILInstruction? falseInst)
{
condition = null;
trueInst = null;

32
ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -19,11 +20,11 @@ @@ -19,11 +20,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.IL
{
/// <summary>
@ -57,13 +58,18 @@ namespace ICSharpCode.Decompiler.IL @@ -57,13 +58,18 @@ namespace ICSharpCode.Decompiler.IL
}
}
Block entryPoint;
Block? entryPoint;
/// <summary>
/// Gets the container's entry point. This is the first block in the Blocks collection.
/// </summary>
public Block EntryPoint {
get { return entryPoint; }
get {
// HACK: While it's possible to have BlockContainers without entry point,
// normally every container must have an entry point according to its invariant.
// Thus it's easier on the transforms if this property returns a non-nullable EntryPoint.
return entryPoint!;
}
private set {
if (entryPoint != null && IsConnected)
entryPoint.IncomingEdgeCount--;
@ -102,7 +108,7 @@ namespace ICSharpCode.Decompiler.IL @@ -102,7 +108,7 @@ namespace ICSharpCode.Decompiler.IL
protected internal override void InstructionCollectionUpdateComplete()
{
base.InstructionCollectionUpdateComplete();
this.EntryPoint = this.Blocks.FirstOrDefault();
this.EntryPoint = this.Blocks.FirstOrDefault()!;
}
protected override void Connected()
@ -174,7 +180,7 @@ namespace ICSharpCode.Decompiler.IL @@ -174,7 +180,7 @@ namespace ICSharpCode.Decompiler.IL
return Blocks[index];
}
protected override void SetChild(int index, ILInstruction value)
protected override void SetChild(int index, ILInstruction? value)
{
if (Blocks[index] != value)
throw new InvalidOperationException("Cannot replace blocks in BlockContainer");
@ -189,12 +195,12 @@ namespace ICSharpCode.Decompiler.IL @@ -189,12 +195,12 @@ namespace ICSharpCode.Decompiler.IL
{
base.CheckInvariant(phase);
Debug.Assert(Blocks.Count > 0 && EntryPoint == Blocks[0]);
Debug.Assert(!IsConnected || EntryPoint?.IncomingEdgeCount >= 1);
Debug.Assert(EntryPoint == null || Parent is ILFunction || !ILRangeIsEmpty);
Debug.Assert(!IsConnected || EntryPoint.IncomingEdgeCount >= 1);
Debug.Assert(Parent is ILFunction || !ILRangeIsEmpty);
Debug.Assert(Blocks.All(b => b.HasFlag(InstructionFlags.EndPointUnreachable)));
Debug.Assert(Blocks.All(b => b.Kind == BlockKind.ControlFlow)); // this also implies that the blocks don't use FinalInstruction
Debug.Assert(TopologicalSort(deleteUnreachableBlocks: true).Count == Blocks.Count, "Container should not have any unreachable blocks");
Block bodyStartBlock;
Block? bodyStartBlock;
switch (Kind)
{
case ContainerKind.Normal:
@ -319,7 +325,7 @@ namespace ICSharpCode.Decompiler.IL @@ -319,7 +325,7 @@ namespace ICSharpCode.Decompiler.IL
Blocks.ReplaceList(newOrder);
}
public static BlockContainer FindClosestContainer(ILInstruction inst)
public static BlockContainer? FindClosestContainer(ILInstruction? inst)
{
while (inst != null)
{
@ -330,18 +336,18 @@ namespace ICSharpCode.Decompiler.IL @@ -330,18 +336,18 @@ namespace ICSharpCode.Decompiler.IL
return null;
}
public static BlockContainer FindClosestSwitchContainer(ILInstruction inst)
public static BlockContainer? FindClosestSwitchContainer(ILInstruction? inst)
{
while (inst != null)
{
if (inst is BlockContainer bc && bc.entryPoint.Instructions.FirstOrDefault() is SwitchInstruction)
if (inst is BlockContainer { Kind: ContainerKind.Switch } bc)
return bc;
inst = inst.Parent;
}
return null;
}
public bool MatchConditionBlock(Block block, out ILInstruction condition, out Block bodyStartBlock)
public bool MatchConditionBlock(Block block, [NotNullWhen(true)] out ILInstruction? condition, [NotNullWhen(true)] out Block? bodyStartBlock)
{
condition = null;
bodyStartBlock = null;

25
ICSharpCode.Decompiler/IL/Instructions/Branch.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -30,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL @@ -30,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL
partial class Branch : SimpleInstruction, IBranchOrLeaveInstruction
{
readonly int targetILOffset;
Block targetBlock;
Block? targetBlock;
public Branch(int targetILOffset) : base(OpCode.Branch)
{
@ -48,7 +49,11 @@ namespace ICSharpCode.Decompiler.IL @@ -48,7 +49,11 @@ namespace ICSharpCode.Decompiler.IL
}
public Block TargetBlock {
get { return targetBlock; }
get {
// HACK: We treat TargetBlock as non-nullable publicly, because it's only null inside
// the ILReader, and becomes non-null once the BlockBuilder has run.
return targetBlock!;
}
set {
if (targetBlock != null && IsConnected)
targetBlock.IncomingEdgeCount--;
@ -62,7 +67,7 @@ namespace ICSharpCode.Decompiler.IL @@ -62,7 +67,7 @@ namespace ICSharpCode.Decompiler.IL
/// Gets the BlockContainer that contains the target block.
/// </summary>
public BlockContainer TargetContainer {
get { return (BlockContainer)targetBlock?.Parent; }
get { return (BlockContainer)targetBlock?.Parent!; }
}
protected override void Connected()
@ -92,9 +97,9 @@ namespace ICSharpCode.Decompiler.IL @@ -92,9 +97,9 @@ namespace ICSharpCode.Decompiler.IL
}
}
internal static bool GetExecutesFinallyBlock(ILInstruction inst, BlockContainer container)
internal static bool GetExecutesFinallyBlock(ILInstruction? inst, BlockContainer? container)
{
for (; inst != container; inst = inst.Parent)
for (; inst != container && inst != null; inst = inst.Parent)
{
if (inst.Parent is TryFinally && inst.SlotInfo == TryFinally.TryBlockSlot)
return true;
@ -107,9 +112,9 @@ namespace ICSharpCode.Decompiler.IL @@ -107,9 +112,9 @@ namespace ICSharpCode.Decompiler.IL
base.CheckInvariant(phase);
if (phase > ILPhase.InILReader)
{
Debug.Assert(targetBlock.Parent is BlockContainer);
Debug.Assert(this.IsDescendantOf(targetBlock.Parent));
Debug.Assert(targetBlock.Parent.Children[targetBlock.ChildIndex] == targetBlock);
Debug.Assert(targetBlock?.Parent is BlockContainer);
Debug.Assert(this.IsDescendantOf(targetBlock!.Parent!));
Debug.Assert(targetBlock!.Parent!.Children[targetBlock.ChildIndex] == targetBlock);
}
}
@ -118,7 +123,7 @@ namespace ICSharpCode.Decompiler.IL @@ -118,7 +123,7 @@ namespace ICSharpCode.Decompiler.IL
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
output.WriteLocalReference(TargetLabel, (object)targetBlock ?? TargetILOffset);
output.WriteLocalReference(TargetLabel, (object?)targetBlock ?? TargetILOffset);
}
}

5
ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2017 Daniel Grunwald
#nullable enable
// Copyright (c) 2017 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -31,7 +32,7 @@ namespace ICSharpCode.Decompiler.IL @@ -31,7 +32,7 @@ namespace ICSharpCode.Decompiler.IL
public static readonly SlotInfo FunctionPointerSlot = new SlotInfo("FunctionPointer", canInlineInto: true);
public static readonly SlotInfo ArgumentSlot = new SlotInfo("Argument", canInlineInto: true, isCollection: true);
ILInstruction functionPointer;
ILInstruction functionPointer = null!;
public readonly InstructionCollection<ILInstruction> Arguments;
public bool IsInstance { get; }
public bool HasExplicitThis { get; }

15
ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -19,7 +20,6 @@ @@ -19,7 +20,6 @@
using System;
using System.Diagnostics;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL
@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler.IL @@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler.IL
/// Gets/Sets the type specified in the 'constrained.' prefix.
/// Returns null if no 'constrained.' prefix exists for this call.
/// </summary>
public IType ConstrainedTo;
public IType? ConstrainedTo;
/// <summary>
/// Gets whether the IL stack was empty at the point of this call.
@ -62,8 +62,7 @@ namespace ICSharpCode.Decompiler.IL @@ -62,8 +62,7 @@ namespace ICSharpCode.Decompiler.IL
protected CallInstruction(OpCode opCode, IMethod method) : base(opCode)
{
Debug.Assert(method != null);
this.Method = method;
this.Method = method ?? throw new ArgumentNullException(nameof(method));
this.Arguments = new InstructionCollection<ILInstruction>(this, 0);
}
@ -78,7 +77,7 @@ namespace ICSharpCode.Decompiler.IL @@ -78,7 +77,7 @@ namespace ICSharpCode.Decompiler.IL
/// Gets the parameter for the argument with the specified index.
/// Returns null for the <c>this</c> parameter.
/// </summary>
public IParameter GetParameter(int argumentIndex)
public IParameter? GetParameter(int argumentIndex)
{
int firstParamIndex = (Method.IsStatic || OpCode == OpCode.NewObj) ? 0 : 1;
if (argumentIndex < firstParamIndex)
@ -160,9 +159,9 @@ namespace ICSharpCode.Decompiler.IL @@ -160,9 +159,9 @@ namespace ICSharpCode.Decompiler.IL
output.Write(')');
}
protected internal sealed override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
protected internal sealed override bool PerformMatch(ILInstruction? other, ref Patterns.Match match)
{
CallInstruction o = other as CallInstruction;
CallInstruction? o = other as CallInstruction;
return o != null && this.OpCode == o.OpCode && this.Method.Equals(o.Method) && this.IsTail == o.IsTail
&& object.Equals(this.ConstrainedTo, o.ConstrainedTo)
&& Patterns.ListMatch.DoMatch(this.Arguments, o.Arguments, ref match);

6
ICSharpCode.Decompiler/IL/Instructions/Comp.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -21,7 +22,6 @@ using System.Diagnostics; @@ -21,7 +22,6 @@ using System.Diagnostics;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.IL
{
@ -231,5 +231,3 @@ namespace ICSharpCode.Decompiler.IL @@ -231,5 +231,3 @@ namespace ICSharpCode.Decompiler.IL
}
}
}

5
ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2016 Siegfried Pammer
#nullable enable
// Copyright (c) 2016 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -172,7 +173,7 @@ namespace ICSharpCode.Decompiler.IL @@ -172,7 +173,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Gets whether the specific binary instruction is compatible with a compound operation on the specified type.
/// </summary>
internal static bool IsBinaryCompatibleWithType(BinaryNumericInstruction binary, IType type, DecompilerSettings settings)
internal static bool IsBinaryCompatibleWithType(BinaryNumericInstruction binary, IType type, DecompilerSettings? settings)
{
if (binary.IsLifted)
{

3
ICSharpCode.Decompiler/IL/Instructions/Conv.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

13
ICSharpCode.Decompiler/IL/Instructions/DeconstructResultInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2020 Siegfried Pammer
#nullable enable
// Copyright (c) 2020 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -47,9 +48,9 @@ namespace ICSharpCode.Decompiler.IL @@ -47,9 +48,9 @@ namespace ICSharpCode.Decompiler.IL
output.Write(')');
}
MatchInstruction FindMatch()
MatchInstruction? FindMatch()
{
for (ILInstruction inst = this; inst != null; inst = inst.Parent)
for (ILInstruction? inst = this; inst != null; inst = inst.Parent)
{
if (inst.Parent is MatchInstruction match && inst != match.TestedOperand)
return match;
@ -60,10 +61,10 @@ namespace ICSharpCode.Decompiler.IL @@ -60,10 +61,10 @@ namespace ICSharpCode.Decompiler.IL
void AdditionalInvariants()
{
var matchInst = FindMatch();
Debug.Assert(matchInst != null && (matchInst.IsDeconstructCall || matchInst.IsDeconstructTuple));
Debug.Assert(Argument.MatchLdLoc(matchInst.Variable));
DebugAssert(matchInst != null && (matchInst.IsDeconstructCall || matchInst.IsDeconstructTuple));
DebugAssert(Argument.MatchLdLoc(matchInst.Variable));
var outParamType = matchInst.GetDeconstructResultType(this.Index);
Debug.Assert(outParamType.GetStackType() == ResultType);
DebugAssert(outParamType.GetStackType() == ResultType);
}
}
}

3
ICSharpCode.Decompiler/IL/Instructions/DefaultValue.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2017 Siegfried Pammer
#nullable enable
// Copyright (c) 2017 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

43
ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2018 Siegfried Pammer
#nullable enable
// Copyright (c) 2018 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -56,7 +57,7 @@ namespace ICSharpCode.Decompiler.IL @@ -56,7 +57,7 @@ namespace ICSharpCode.Decompiler.IL
public struct CSharpArgumentInfo
{
public string Name { get; set; }
public string? Name { get; set; }
public CSharpArgumentInfoFlags Flags { get; set; }
public IType CompileTimeType { get; set; }
@ -66,9 +67,9 @@ namespace ICSharpCode.Decompiler.IL @@ -66,9 +67,9 @@ namespace ICSharpCode.Decompiler.IL
partial class DynamicInstruction
{
public CSharpBinderFlags BinderFlags { get; }
public IType CallingContext { get; }
public IType? CallingContext { get; }
protected DynamicInstruction(OpCode opCode, CSharpBinderFlags binderFlags, IType context)
protected DynamicInstruction(OpCode opCode, CSharpBinderFlags binderFlags, IType? context)
: base(opCode)
{
BinderFlags = binderFlags;
@ -141,10 +142,10 @@ namespace ICSharpCode.Decompiler.IL @@ -141,10 +142,10 @@ namespace ICSharpCode.Decompiler.IL
output.Write(')');
}
public DynamicConvertInstruction(CSharpBinderFlags binderFlags, IType type, IType context, ILInstruction argument)
public DynamicConvertInstruction(CSharpBinderFlags binderFlags, IType type, IType? context, ILInstruction argument)
: base(OpCode.DynamicConvertInstruction, binderFlags, context)
{
Type = type;
this.type = type;
Argument = argument;
}
@ -171,7 +172,7 @@ namespace ICSharpCode.Decompiler.IL @@ -171,7 +172,7 @@ namespace ICSharpCode.Decompiler.IL
public IReadOnlyList<IType> TypeArguments { get; }
public IReadOnlyList<CSharpArgumentInfo> ArgumentInfo { get; }
public DynamicInvokeMemberInstruction(CSharpBinderFlags binderFlags, string name, IType[] typeArguments, IType context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
public DynamicInvokeMemberInstruction(CSharpBinderFlags binderFlags, string name, IType[]? typeArguments, IType? context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
: base(OpCode.DynamicInvokeMemberInstruction, binderFlags, context)
{
Name = name;
@ -216,10 +217,10 @@ namespace ICSharpCode.Decompiler.IL @@ -216,10 +217,10 @@ namespace ICSharpCode.Decompiler.IL
partial class DynamicGetMemberInstruction
{
public string Name { get; }
public string? Name { get; }
public CSharpArgumentInfo TargetArgumentInfo { get; }
public DynamicGetMemberInstruction(CSharpBinderFlags binderFlags, string name, IType context, CSharpArgumentInfo targetArgumentInfo, ILInstruction target)
public DynamicGetMemberInstruction(CSharpBinderFlags binderFlags, string? name, IType? context, CSharpArgumentInfo targetArgumentInfo, ILInstruction target)
: base(OpCode.DynamicGetMemberInstruction, binderFlags, context)
{
Name = name;
@ -249,11 +250,11 @@ namespace ICSharpCode.Decompiler.IL @@ -249,11 +250,11 @@ namespace ICSharpCode.Decompiler.IL
partial class DynamicSetMemberInstruction
{
public string Name { get; }
public string? Name { get; }
public CSharpArgumentInfo TargetArgumentInfo { get; }
public CSharpArgumentInfo ValueArgumentInfo { get; }
public DynamicSetMemberInstruction(CSharpBinderFlags binderFlags, string name, IType context, CSharpArgumentInfo targetArgumentInfo, ILInstruction target, CSharpArgumentInfo valueArgumentInfo, ILInstruction value)
public DynamicSetMemberInstruction(CSharpBinderFlags binderFlags, string? name, IType? context, CSharpArgumentInfo targetArgumentInfo, ILInstruction target, CSharpArgumentInfo valueArgumentInfo, ILInstruction value)
: base(OpCode.DynamicSetMemberInstruction, binderFlags, context)
{
Name = name;
@ -293,7 +294,7 @@ namespace ICSharpCode.Decompiler.IL @@ -293,7 +294,7 @@ namespace ICSharpCode.Decompiler.IL
{
public IReadOnlyList<CSharpArgumentInfo> ArgumentInfo { get; }
public DynamicGetIndexInstruction(CSharpBinderFlags binderFlags, IType context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
public DynamicGetIndexInstruction(CSharpBinderFlags binderFlags, IType? context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
: base(OpCode.DynamicGetIndexInstruction, binderFlags, context)
{
ArgumentInfo = argumentInfo;
@ -325,7 +326,7 @@ namespace ICSharpCode.Decompiler.IL @@ -325,7 +326,7 @@ namespace ICSharpCode.Decompiler.IL
{
public IReadOnlyList<CSharpArgumentInfo> ArgumentInfo { get; }
public DynamicSetIndexInstruction(CSharpBinderFlags binderFlags, IType context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
public DynamicSetIndexInstruction(CSharpBinderFlags binderFlags, IType? context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
: base(OpCode.DynamicSetIndexInstruction, binderFlags, context)
{
ArgumentInfo = argumentInfo;
@ -355,11 +356,11 @@ namespace ICSharpCode.Decompiler.IL @@ -355,11 +356,11 @@ namespace ICSharpCode.Decompiler.IL
partial class DynamicInvokeConstructorInstruction
{
readonly IType resultType;
readonly IType? resultType;
public IReadOnlyList<CSharpArgumentInfo> ArgumentInfo { get; }
public DynamicInvokeConstructorInstruction(CSharpBinderFlags binderFlags, IType type, IType context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
public DynamicInvokeConstructorInstruction(CSharpBinderFlags binderFlags, IType? type, IType? context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
: base(OpCode.DynamicInvokeConstructorInstruction, binderFlags, context)
{
ArgumentInfo = argumentInfo;
@ -395,7 +396,7 @@ namespace ICSharpCode.Decompiler.IL @@ -395,7 +396,7 @@ namespace ICSharpCode.Decompiler.IL
public CSharpArgumentInfo RightArgumentInfo { get; }
public ExpressionType Operation { get; }
public DynamicBinaryOperatorInstruction(CSharpBinderFlags binderFlags, ExpressionType operation, IType context, CSharpArgumentInfo leftArgumentInfo, ILInstruction left, CSharpArgumentInfo rightArgumentInfo, ILInstruction right)
public DynamicBinaryOperatorInstruction(CSharpBinderFlags binderFlags, ExpressionType operation, IType? context, CSharpArgumentInfo leftArgumentInfo, ILInstruction left, CSharpArgumentInfo rightArgumentInfo, ILInstruction right)
: base(OpCode.DynamicBinaryOperatorInstruction, binderFlags, context)
{
Operation = operation;
@ -437,7 +438,7 @@ namespace ICSharpCode.Decompiler.IL @@ -437,7 +438,7 @@ namespace ICSharpCode.Decompiler.IL
public CSharpArgumentInfo RightArgumentInfo { get; }
public ExpressionType Operation { get; }
public DynamicLogicOperatorInstruction(CSharpBinderFlags binderFlags, ExpressionType operation, IType context, CSharpArgumentInfo leftArgumentInfo, ILInstruction left, CSharpArgumentInfo rightArgumentInfo, ILInstruction right)
public DynamicLogicOperatorInstruction(CSharpBinderFlags binderFlags, ExpressionType operation, IType? context, CSharpArgumentInfo leftArgumentInfo, ILInstruction left, CSharpArgumentInfo rightArgumentInfo, ILInstruction right)
: base(OpCode.DynamicLogicOperatorInstruction, binderFlags, context)
{
Operation = operation;
@ -486,7 +487,7 @@ namespace ICSharpCode.Decompiler.IL @@ -486,7 +487,7 @@ namespace ICSharpCode.Decompiler.IL
public CSharpArgumentInfo OperandArgumentInfo { get; }
public ExpressionType Operation { get; }
public DynamicUnaryOperatorInstruction(CSharpBinderFlags binderFlags, ExpressionType operation, IType context, CSharpArgumentInfo operandArgumentInfo, ILInstruction operand)
public DynamicUnaryOperatorInstruction(CSharpBinderFlags binderFlags, ExpressionType operation, IType? context, CSharpArgumentInfo operandArgumentInfo, ILInstruction operand)
: base(OpCode.DynamicUnaryOperatorInstruction, binderFlags, context)
{
Operation = operation;
@ -533,7 +534,7 @@ namespace ICSharpCode.Decompiler.IL @@ -533,7 +534,7 @@ namespace ICSharpCode.Decompiler.IL
{
public IReadOnlyList<CSharpArgumentInfo> ArgumentInfo { get; }
public DynamicInvokeInstruction(CSharpBinderFlags binderFlags, IType context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
public DynamicInvokeInstruction(CSharpBinderFlags binderFlags, IType? context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
: base(OpCode.DynamicInvokeInstruction, binderFlags, context)
{
ArgumentInfo = argumentInfo;
@ -562,9 +563,9 @@ namespace ICSharpCode.Decompiler.IL @@ -562,9 +563,9 @@ namespace ICSharpCode.Decompiler.IL
partial class DynamicIsEventInstruction
{
public string Name { get; }
public string? Name { get; }
public DynamicIsEventInstruction(CSharpBinderFlags binderFlags, string name, IType context, ILInstruction argument)
public DynamicIsEventInstruction(CSharpBinderFlags binderFlags, string? name, IType? context, ILInstruction argument)
: base(OpCode.DynamicIsEventInstruction, binderFlags, context)
{
Name = name;

7
ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs

@ -1,7 +1,4 @@ @@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
#nullable enable
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL
@ -13,7 +10,7 @@ namespace ICSharpCode.Decompiler.IL @@ -13,7 +10,7 @@ namespace ICSharpCode.Decompiler.IL
public ExpressionTreeCast(IType type, ILInstruction argument, bool isChecked)
: base(OpCode.ExpressionTreeCast, argument)
{
this.Type = type;
this.type = type;
this.IsChecked = isChecked;
}

39
ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -18,7 +19,6 @@ @@ -18,7 +19,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.IL @@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.IL
/// May be null for functions that were not constructed from metadata,
/// e.g., expression trees.
/// </summary>
public readonly IMethod Method;
public readonly IMethod? Method;
/// <summary>
/// Gets the generic context of this function.
@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.IL @@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.IL
/// has no effect, as the name should not be used in the final AST construction.
/// </para>
/// </summary>
public string Name;
public string? Name;
/// <summary>
/// Size of the IL code in this function.
@ -71,7 +71,7 @@ namespace ICSharpCode.Decompiler.IL @@ -71,7 +71,7 @@ namespace ICSharpCode.Decompiler.IL
/// Gets the scope in which the local function is declared.
/// Returns null, if this is not a local function.
/// </summary>
public BlockContainer DeclarationScope { get; internal set; }
public BlockContainer? DeclarationScope { get; internal set; }
/// <summary>
/// Gets the set of captured variables by this ILFunction.
@ -108,17 +108,17 @@ namespace ICSharpCode.Decompiler.IL @@ -108,17 +108,17 @@ namespace ICSharpCode.Decompiler.IL
/// Return element type -- if the async method returns Task{T}, this field stores T.
/// If the async method returns Task or void, this field stores void.
/// </summary>
public IType AsyncReturnType;
public IType? AsyncReturnType;
/// <summary>
/// If this function is an iterator/async, this field stores the compiler-generated MoveNext() method.
/// </summary>
public IMethod MoveNextMethod;
public IMethod? MoveNextMethod;
/// <summary>
/// If this function is a local function, this field stores the reduced version of the function.
/// </summary>
internal TypeSystem.Implementation.LocalFunctionMethod ReducedMethod;
internal TypeSystem.Implementation.LocalFunctionMethod? ReducedMethod;
public DebugInfo.AsyncDebugInfo AsyncDebugInfo;
@ -131,8 +131,10 @@ namespace ICSharpCode.Decompiler.IL @@ -131,8 +131,10 @@ namespace ICSharpCode.Decompiler.IL
get {
if (ctorCallStart == int.MinValue)
{
if (!this.Method.IsConstructor || this.Method.IsStatic)
if (this.Method == null || !this.Method.IsConstructor || this.Method.IsStatic)
{
ctorCallStart = -1;
}
else
{
ctorCallStart = this.Descendants.FirstOrDefault(d => d is CallInstruction call && !(call is NewObj)
@ -150,7 +152,7 @@ namespace ICSharpCode.Decompiler.IL @@ -150,7 +152,7 @@ namespace ICSharpCode.Decompiler.IL
/// T is the delegate type that matches the signature of this method.
/// Otherwise this must be null.
/// </summary>
public IType DelegateType;
public IType? DelegateType;
ILFunctionKind kind;
@ -181,7 +183,7 @@ namespace ICSharpCode.Decompiler.IL @@ -181,7 +183,7 @@ namespace ICSharpCode.Decompiler.IL
/// where the stack is empty, nop instructions, and the instruction following
/// a call instruction
/// </summary>
public List<int> SequencePointCandidates { get; set; }
public List<int>? SequencePointCandidates { get; set; }
/// <summary>
/// Constructs a new ILFunction from the given metadata and with the given ILAst body.
@ -408,20 +410,9 @@ namespace ICSharpCode.Decompiler.IL @@ -408,20 +410,9 @@ namespace ICSharpCode.Decompiler.IL
int helperVariableCount;
public ILVariable RegisterVariable(VariableKind kind, IType type, string name = null)
{
return RegisterVariable(kind, type, type.GetStackType(), name);
}
public ILVariable RegisterVariable(VariableKind kind, StackType stackType, string name = null)
{
var type = Method.Compilation.FindType(stackType.ToKnownTypeCode());
return RegisterVariable(kind, type, stackType, name);
}
ILVariable RegisterVariable(VariableKind kind, IType type, StackType stackType, string name = null)
public ILVariable RegisterVariable(VariableKind kind, IType type, string? name = null)
{
var variable = new ILVariable(kind, type, stackType);
var variable = new ILVariable(kind, type);
if (string.IsNullOrWhiteSpace(name))
{
name = "I_" + (helperVariableCount++);

22
ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs

@ -21,9 +21,11 @@ @@ -21,9 +21,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using ICSharpCode.Decompiler.IL.Patterns;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
@ -60,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL @@ -60,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL
this.OpCode = opCode;
}
protected void ValidateChild(ILInstruction inst)
protected void ValidateChild(ILInstruction? inst)
{
if (inst == null)
throw new ArgumentNullException(nameof(inst));
@ -69,6 +71,16 @@ namespace ICSharpCode.Decompiler.IL @@ -69,6 +71,16 @@ namespace ICSharpCode.Decompiler.IL
// make sure to read the remarks on the ReplaceWith() method.
}
internal static void DebugAssert([DoesNotReturnIf(false)] bool b)
{
Debug.Assert(b);
}
internal static void DebugAssert([DoesNotReturnIf(false)] bool b, string msg)
{
Debug.Assert(b, msg);
}
[Conditional("DEBUG")]
internal virtual void CheckInvariant(ILPhase phase)
{
@ -493,7 +505,7 @@ namespace ICSharpCode.Decompiler.IL @@ -493,7 +505,7 @@ namespace ICSharpCode.Decompiler.IL
internal ChildrenEnumerator(ILInstruction inst)
{
Debug.Assert(inst != null);
DebugAssert(inst != null);
this.inst = inst;
this.pos = -1;
this.end = inst!.GetChildCount();
@ -899,9 +911,9 @@ namespace ICSharpCode.Decompiler.IL @@ -899,9 +911,9 @@ namespace ICSharpCode.Decompiler.IL
/// If extraction is not possible, the ILAst is left unmodified and the function returns null.
/// May return null if extraction is not possible.
/// </summary>
public ILVariable Extract()
public ILVariable Extract(ILTransformContext context)
{
return Transforms.ExtractionContext.Extract(this);
return Transforms.ExtractionContext.Extract(this, context);
}
/// <summary>
@ -950,7 +962,7 @@ namespace ICSharpCode.Decompiler.IL @@ -950,7 +962,7 @@ namespace ICSharpCode.Decompiler.IL
public interface IInstructionWithMethodOperand
{
IMethod Method { get; }
IMethod? Method { get; }
}
public interface ILiftableInstruction

5
ICSharpCode.Decompiler/IL/Instructions/ILVariableCollection.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2016 Daniel Grunwald
#nullable enable
// Copyright (c) 2016 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -128,7 +129,7 @@ namespace ICSharpCode.Decompiler.IL @@ -128,7 +129,7 @@ namespace ICSharpCode.Decompiler.IL
{
// However, remove unused this-parameters of delegates, expression trees, etc.
// These will be replaced with the top-level function's this-parameter.
if (v.Index == -1 && v.Function.Kind != ILFunctionKind.TopLevelFunction)
if (v.Index == -1 && v.Function!.Kind != ILFunctionKind.TopLevelFunction)
return true;
return false;
}

9
ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -35,7 +36,7 @@ namespace ICSharpCode.Decompiler.IL @@ -35,7 +36,7 @@ namespace ICSharpCode.Decompiler.IL
/// </remarks>
partial class IfInstruction : ILInstruction
{
public IfInstruction(ILInstruction condition, ILInstruction trueInst, ILInstruction falseInst = null) : base(OpCode.IfInstruction)
public IfInstruction(ILInstruction condition, ILInstruction trueInst, ILInstruction? falseInst = null) : base(OpCode.IfInstruction)
{
this.Condition = condition;
this.TrueInst = trueInst;
@ -47,7 +48,7 @@ namespace ICSharpCode.Decompiler.IL @@ -47,7 +48,7 @@ namespace ICSharpCode.Decompiler.IL
return new IfInstruction(lhs, rhs, new LdcI4(0));
}
public static IfInstruction LogicOr(ILInstruction lhs, ILInstruction rhs)
public static IfInstruction LogicOr(ILInstruction lhs, ILInstruction? rhs)
{
return new IfInstruction(lhs, new LdcI4(1), rhs);
}
@ -126,7 +127,7 @@ namespace ICSharpCode.Decompiler.IL @@ -126,7 +127,7 @@ namespace ICSharpCode.Decompiler.IL
if (slot == IfInstruction.ConditionSlot)
return true;
if (slot == IfInstruction.TrueInstSlot || slot == IfInstruction.FalseInstSlot || slot == NullCoalescingInstruction.FallbackInstSlot)
return IsInConditionSlot(inst.Parent);
return IsInConditionSlot(inst.Parent!);
if (inst.Parent is Comp comp)
{
if (comp.Left == inst && comp.Right.MatchLdcI4(0))

3
ICSharpCode.Decompiler/IL/Instructions/LdFlda.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

3
ICSharpCode.Decompiler/IL/Instructions/LdLen.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

13
ICSharpCode.Decompiler/IL/Instructions/Leave.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -32,9 +33,9 @@ namespace ICSharpCode.Decompiler.IL @@ -32,9 +33,9 @@ namespace ICSharpCode.Decompiler.IL
/// </remarks>
partial class Leave : ILInstruction, IBranchOrLeaveInstruction
{
BlockContainer targetContainer;
BlockContainer? targetContainer;
public Leave(BlockContainer targetContainer, ILInstruction value = null) : base(OpCode.Leave)
public Leave(BlockContainer? targetContainer, ILInstruction? value = null) : base(OpCode.Leave)
{
// Note: ILReader will create Leave instructions with targetContainer==null to represent 'endfinally',
// the targetContainer will then be filled in by BlockBuilder
@ -54,7 +55,7 @@ namespace ICSharpCode.Decompiler.IL @@ -54,7 +55,7 @@ namespace ICSharpCode.Decompiler.IL
}
public BlockContainer TargetContainer {
get { return targetContainer; }
get { return targetContainer!; }
set {
if (targetContainer != null && IsConnected)
targetContainer.LeaveCount--;
@ -109,8 +110,8 @@ namespace ICSharpCode.Decompiler.IL @@ -109,8 +110,8 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(targetContainer));
Debug.Assert(phase <= ILPhase.InILReader || phase == ILPhase.InAsyncAwait || value.ResultType == targetContainer.ResultType);
Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(targetContainer!));
Debug.Assert(phase <= ILPhase.InILReader || phase == ILPhase.InAsyncAwait || value.ResultType == targetContainer!.ResultType);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)

3
ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2017 Siegfried Pammer
#nullable enable
// Copyright (c) 2017 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

3
ICSharpCode.Decompiler/IL/Instructions/LogicInstructions.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2017 Daniel Grunwald
#nullable enable
// Copyright (c) 2017 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

30
ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2020 Siegfried Pammer
#nullable enable
// Copyright (c) 2020 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -18,10 +19,9 @@ @@ -18,10 +19,9 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Diagnostics.CodeAnalysis;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL
{
partial class MatchInstruction : ILInstruction
@ -96,7 +96,7 @@ namespace ICSharpCode.Decompiler.IL @@ -96,7 +96,7 @@ namespace ICSharpCode.Decompiler.IL
public int NumPositionalPatterns {
get {
if (IsDeconstructCall)
return method.Parameters.Count - (method.IsStatic ? 1 : 0);
return method!.Parameters.Count - (method.IsStatic ? 1 : 0);
else if (IsDeconstructTuple)
return TupleType.GetTupleElementTypes(variable.Type).Length;
else
@ -118,7 +118,7 @@ namespace ICSharpCode.Decompiler.IL @@ -118,7 +118,7 @@ namespace ICSharpCode.Decompiler.IL
/// (even if the pattern fails to match!).
/// The pattern matching instruction evaluates to 1 (as I4) if the pattern matches, or 0 otherwise.
/// </summary>
public static bool IsPatternMatch(ILInstruction inst, out ILInstruction testedOperand)
public static bool IsPatternMatch(ILInstruction? inst, [NotNullWhen(true)] out ILInstruction? testedOperand)
{
switch (inst)
{
@ -153,9 +153,9 @@ namespace ICSharpCode.Decompiler.IL @@ -153,9 +153,9 @@ namespace ICSharpCode.Decompiler.IL
{
if (this.IsDeconstructCall)
{
int firstOutParam = (method.IsStatic ? 1 : 0);
var outParamType = this.Method.Parameters[firstOutParam + index].Type;
if (!(outParamType is ByReferenceType brt))
int firstOutParam = (method!.IsStatic ? 1 : 0);
var outParamType = method.Parameters[firstOutParam + index].Type;
if (outParamType is not ByReferenceType brt)
throw new InvalidOperationException("deconstruct out param must be by reference");
return brt.ElementType;
}
@ -185,8 +185,8 @@ namespace ICSharpCode.Decompiler.IL @@ -185,8 +185,8 @@ namespace ICSharpCode.Decompiler.IL
Debug.Assert(SubPatterns.Count >= NumPositionalPatterns);
foreach (var subPattern in SubPatterns)
{
if (!IsPatternMatch(subPattern, out ILInstruction operand))
Debug.Fail("Sub-Pattern must be a valid pattern");
if (!IsPatternMatch(subPattern, out ILInstruction? operand))
throw new InvalidOperationException("Sub-Pattern must be a valid pattern");
// the first child is TestedOperand
int subPatternIndex = subPattern.ChildIndex - 1;
if (subPatternIndex < NumPositionalPatterns)
@ -210,8 +210,11 @@ namespace ICSharpCode.Decompiler.IL @@ -210,8 +210,11 @@ namespace ICSharpCode.Decompiler.IL
}
}
internal static bool IsDeconstructMethod(IMethod method)
internal static bool IsDeconstructMethod(IMethod? method)
{
if (method == null
)
return false;
if (method.Name != "Deconstruct")
return false;
if (method.ReturnType.Kind != TypeKind.Void)
@ -260,7 +263,10 @@ namespace ICSharpCode.Decompiler.IL @@ -260,7 +263,10 @@ namespace ICSharpCode.Decompiler.IL
if (IsDeconstructCall)
{
output.Write(".deconstruct[");
method.WriteTo(output);
if (method == null)
output.Write("<null>");
else
method.WriteTo(output);
output.Write(']');
}
if (IsDeconstructTuple)

3
ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

3
ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2017 Siegfried Pammer
#nullable enable
// Copyright (c) 2017 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

3
ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2018 Daniel Grunwald
#nullable enable
// Copyright (c) 2018 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

75
ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -16,8 +17,9 @@ @@ -16,8 +17,9 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using ICSharpCode.Decompiler.TypeSystem;
using System.Diagnostics.CodeAnalysis;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL
{
partial class ILInstruction
@ -73,13 +75,13 @@ namespace ICSharpCode.Decompiler.IL @@ -73,13 +75,13 @@ namespace ICSharpCode.Decompiler.IL
return MatchLdcI(out long v) && v == val;
}
public bool MatchLdLoc(ILVariable variable)
public bool MatchLdLoc(ILVariable? variable)
{
var inst = this as LdLoc;
return inst != null && inst.Variable == variable;
}
public bool MatchLdLoca(ILVariable variable)
public bool MatchLdLoca(ILVariable? variable)
{
var inst = this as LdLoca;
return inst != null && inst.Variable == variable;
@ -88,7 +90,7 @@ namespace ICSharpCode.Decompiler.IL @@ -88,7 +90,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Matches either ldloc (if the variable is a reference type), or ldloca (otherwise).
/// </summary>
public bool MatchLdLocRef(ILVariable variable)
public bool MatchLdLocRef(ILVariable? variable)
{
return MatchLdLocRef(out var v) && v == variable;
}
@ -96,7 +98,7 @@ namespace ICSharpCode.Decompiler.IL @@ -96,7 +98,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Matches either ldloc (if the variable is a reference type), or ldloca (otherwise).
/// </summary>
public bool MatchLdLocRef(out ILVariable variable)
public bool MatchLdLocRef([NotNullWhen(true)] out ILVariable? variable)
{
switch (this)
{
@ -118,7 +120,7 @@ namespace ICSharpCode.Decompiler.IL @@ -118,7 +120,7 @@ namespace ICSharpCode.Decompiler.IL
return inst != null && inst.Variable.Kind == VariableKind.Parameter && inst.Variable.Index < 0;
}
public bool MatchStLoc(out ILVariable variable)
public bool MatchStLoc([NotNullWhen(true)] out ILVariable? variable)
{
var inst = this as StLoc;
if (inst != null)
@ -130,7 +132,7 @@ namespace ICSharpCode.Decompiler.IL @@ -130,7 +132,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchStLoc(ILVariable variable, out ILInstruction value)
public bool MatchStLoc(ILVariable? variable, [NotNullWhen(true)] out ILInstruction? value)
{
var inst = this as StLoc;
if (inst != null && inst.Variable == variable)
@ -142,7 +144,7 @@ namespace ICSharpCode.Decompiler.IL @@ -142,7 +144,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchLdLen(StackType type, out ILInstruction array)
public bool MatchLdLen(StackType type, [NotNullWhen(true)] out ILInstruction? array)
{
var inst = this as LdLen;
if (inst != null && inst.ResultType == type)
@ -154,7 +156,7 @@ namespace ICSharpCode.Decompiler.IL @@ -154,7 +156,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchReturn(out ILInstruction value)
public bool MatchReturn([NotNullWhen(true)] out ILInstruction? value)
{
var inst = this as Leave;
if (inst != null && inst.IsLeavingFunction)
@ -166,7 +168,7 @@ namespace ICSharpCode.Decompiler.IL @@ -166,7 +168,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchBranch(out Block targetBlock)
public bool MatchBranch([NotNullWhen(true)] out Block? targetBlock)
{
var inst = this as Branch;
if (inst != null)
@ -178,13 +180,13 @@ namespace ICSharpCode.Decompiler.IL @@ -178,13 +180,13 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchBranch(Block targetBlock)
public bool MatchBranch(Block? targetBlock)
{
var inst = this as Branch;
return inst != null && inst.TargetBlock == targetBlock;
}
public bool MatchLeave(out BlockContainer targetContainer, out ILInstruction value)
public bool MatchLeave([NotNullWhen(true)] out BlockContainer? targetContainer, [NotNullWhen(true)] out ILInstruction? value)
{
var inst = this as Leave;
if (inst != null)
@ -198,7 +200,7 @@ namespace ICSharpCode.Decompiler.IL @@ -198,7 +200,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchLeave(BlockContainer targetContainer, out ILInstruction value)
public bool MatchLeave(BlockContainer? targetContainer, [NotNullWhen(true)] out ILInstruction? value)
{
var inst = this as Leave;
if (inst != null && targetContainer == inst.TargetContainer)
@ -210,7 +212,7 @@ namespace ICSharpCode.Decompiler.IL @@ -210,7 +212,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchLeave(out BlockContainer targetContainer)
public bool MatchLeave([NotNullWhen(true)] out BlockContainer? targetContainer)
{
var inst = this as Leave;
if (inst != null && inst.Value.MatchNop())
@ -222,16 +224,15 @@ namespace ICSharpCode.Decompiler.IL @@ -222,16 +224,15 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchLeave(BlockContainer targetContainer)
public bool MatchLeave(BlockContainer? targetContainer)
{
var inst = this as Leave;
return inst != null && inst.TargetContainer == targetContainer && inst.Value.MatchNop();
}
public bool MatchIfInstruction(out ILInstruction condition, out ILInstruction trueInst, out ILInstruction falseInst)
public bool MatchIfInstruction([NotNullWhen(true)] out ILInstruction? condition, [NotNullWhen(true)] out ILInstruction? trueInst, [NotNullWhen(true)] out ILInstruction? falseInst)
{
var inst = this as IfInstruction;
if (inst != null)
if (this is IfInstruction inst)
{
condition = inst.Condition;
trueInst = inst.TrueInst;
@ -244,7 +245,7 @@ namespace ICSharpCode.Decompiler.IL @@ -244,7 +245,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchIfInstructionPositiveCondition(out ILInstruction condition, out ILInstruction trueInst, out ILInstruction falseInst)
public bool MatchIfInstructionPositiveCondition([NotNullWhen(true)] out ILInstruction? condition, [NotNullWhen(true)] out ILInstruction? trueInst, [NotNullWhen(true)] out ILInstruction? falseInst)
{
if (MatchIfInstruction(out condition, out trueInst, out falseInst))
{
@ -252,7 +253,7 @@ namespace ICSharpCode.Decompiler.IL @@ -252,7 +253,7 @@ namespace ICSharpCode.Decompiler.IL
while (condition.MatchLogicNot(out var arg))
{
condition = arg;
ILInstruction tmp = trueInst;
ILInstruction? tmp = trueInst;
trueInst = falseInst;
falseInst = tmp;
}
@ -264,7 +265,7 @@ namespace ICSharpCode.Decompiler.IL @@ -264,7 +265,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Matches an if instruction where the false instruction is a nop.
/// </summary>
public bool MatchIfInstruction(out ILInstruction condition, out ILInstruction trueInst)
public bool MatchIfInstruction([NotNullWhen(true)] out ILInstruction? condition, [NotNullWhen(true)] out ILInstruction? trueInst)
{
var inst = this as IfInstruction;
if (inst != null && inst.FalseInst.MatchNop())
@ -283,7 +284,7 @@ namespace ICSharpCode.Decompiler.IL @@ -283,7 +284,7 @@ namespace ICSharpCode.Decompiler.IL
/// Note: unlike C# '&amp;&amp;', this instruction is not limited to booleans,
/// but allows passing through arbitrary I4 values on the rhs (but not on the lhs).
/// </summary>
public bool MatchLogicAnd(out ILInstruction lhs, out ILInstruction rhs)
public bool MatchLogicAnd([NotNullWhen(true)] out ILInstruction? lhs, [NotNullWhen(true)] out ILInstruction? rhs)
{
var inst = this as IfInstruction;
if (inst != null && inst.FalseInst.MatchLdcI4(0))
@ -302,7 +303,7 @@ namespace ICSharpCode.Decompiler.IL @@ -302,7 +303,7 @@ namespace ICSharpCode.Decompiler.IL
/// Note: unlike C# '||', this instruction is not limited to booleans,
/// but allows passing through arbitrary I4 values on the rhs (but not on the lhs).
/// </summary>
public bool MatchLogicOr(out ILInstruction lhs, out ILInstruction rhs)
public bool MatchLogicOr([NotNullWhen(true)] out ILInstruction? lhs, [NotNullWhen(true)] out ILInstruction? rhs)
{
var inst = this as IfInstruction;
if (inst != null && inst.TrueInst.MatchLdcI4(1))
@ -319,7 +320,7 @@ namespace ICSharpCode.Decompiler.IL @@ -319,7 +320,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Matches an logical negation.
/// </summary>
public bool MatchLogicNot(out ILInstruction arg)
public bool MatchLogicNot([NotNullWhen(true)] out ILInstruction? arg)
{
if (this is Comp comp && comp.Kind == ComparisonKind.Equality
&& comp.LiftingKind == ComparisonLiftingKind.None
@ -332,7 +333,7 @@ namespace ICSharpCode.Decompiler.IL @@ -332,7 +333,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchTryCatchHandler(out ILVariable variable)
public bool MatchTryCatchHandler([NotNullWhen(true)] out ILVariable? variable)
{
var inst = this as TryCatchHandler;
if (inst != null)
@ -347,7 +348,7 @@ namespace ICSharpCode.Decompiler.IL @@ -347,7 +348,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Matches comp(left == right) or logic.not(comp(left != right)).
/// </summary>
public bool MatchCompEquals(out ILInstruction left, out ILInstruction right)
public bool MatchCompEquals([NotNullWhen(true)] out ILInstruction? left, [NotNullWhen(true)] out ILInstruction? right)
{
ILInstruction thisInst = this;
var compKind = ComparisonKind.Equality;
@ -376,7 +377,7 @@ namespace ICSharpCode.Decompiler.IL @@ -376,7 +377,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Matches 'comp(arg == ldnull)'
/// </summary>
public bool MatchCompEqualsNull(out ILInstruction arg)
public bool MatchCompEqualsNull([NotNullWhen(true)] out ILInstruction? arg)
{
if (!MatchCompEquals(out var left, out var right))
{
@ -403,7 +404,7 @@ namespace ICSharpCode.Decompiler.IL @@ -403,7 +404,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Matches 'comp(arg != ldnull)'
/// </summary>
public bool MatchCompNotEqualsNull(out ILInstruction arg)
public bool MatchCompNotEqualsNull([NotNullWhen(true)] out ILInstruction? arg)
{
if (!MatchCompNotEquals(out var left, out var right))
{
@ -430,7 +431,7 @@ namespace ICSharpCode.Decompiler.IL @@ -430,7 +431,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Matches comp(left != right) or logic.not(comp(left == right)).
/// </summary>
public bool MatchCompNotEquals(out ILInstruction left, out ILInstruction right)
public bool MatchCompNotEquals([NotNullWhen(true)] out ILInstruction? left, [NotNullWhen(true)] out ILInstruction? right)
{
ILInstruction thisInst = this;
var compKind = ComparisonKind.Inequality;
@ -456,7 +457,7 @@ namespace ICSharpCode.Decompiler.IL @@ -456,7 +457,7 @@ namespace ICSharpCode.Decompiler.IL
}
}
public bool MatchLdFld(out ILInstruction target, out IField field)
public bool MatchLdFld([NotNullWhen(true)] out ILInstruction? target, [NotNullWhen(true)] out IField? field)
{
if (this is LdObj ldobj && ldobj.Target is LdFlda ldflda && ldobj.UnalignedPrefix == 0 && !ldobj.IsVolatile)
{
@ -472,7 +473,7 @@ namespace ICSharpCode.Decompiler.IL @@ -472,7 +473,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchLdsFld(out IField field)
public bool MatchLdsFld([NotNullWhen(true)] out IField? field)
{
if (this is LdObj ldobj && ldobj.Target is LdsFlda ldsflda && ldobj.UnalignedPrefix == 0 && !ldobj.IsVolatile)
{
@ -483,12 +484,12 @@ namespace ICSharpCode.Decompiler.IL @@ -483,12 +484,12 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchLdsFld(IField field)
public bool MatchLdsFld(IField? field)
{
return MatchLdsFld(out var f) && f.Equals(field);
}
public bool MatchStsFld(out IField field, out ILInstruction value)
public bool MatchStsFld([NotNullWhen(true)] out IField? field, [NotNullWhen(true)] out ILInstruction? value)
{
if (this is StObj stobj && stobj.Target is LdsFlda ldsflda && stobj.UnalignedPrefix == 0 && !stobj.IsVolatile)
{
@ -501,7 +502,7 @@ namespace ICSharpCode.Decompiler.IL @@ -501,7 +502,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchStFld(out ILInstruction target, out IField field, out ILInstruction value)
public bool MatchStFld([NotNullWhen(true)] out ILInstruction? target, [NotNullWhen(true)] out IField? field, [NotNullWhen(true)] out ILInstruction? value)
{
if (this is StObj stobj && stobj.Target is LdFlda ldflda && stobj.UnalignedPrefix == 0 && !stobj.IsVolatile)
{
@ -522,7 +523,7 @@ namespace ICSharpCode.Decompiler.IL @@ -522,7 +523,7 @@ namespace ICSharpCode.Decompiler.IL
return op != null && op.Operator == @operator;
}
public bool MatchBinaryNumericInstruction(BinaryNumericOperator @operator, out ILInstruction left, out ILInstruction right)
public bool MatchBinaryNumericInstruction(BinaryNumericOperator @operator, [NotNullWhen(true)] out ILInstruction? left, [NotNullWhen(true)] out ILInstruction? right)
{
var op = this as BinaryNumericInstruction;
if (op != null && op.Operator == @operator)
@ -536,7 +537,7 @@ namespace ICSharpCode.Decompiler.IL @@ -536,7 +537,7 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
public bool MatchBinaryNumericInstruction(out BinaryNumericOperator @operator, out ILInstruction left, out ILInstruction right)
public bool MatchBinaryNumericInstruction(out BinaryNumericOperator @operator, [NotNullWhen(true)] out ILInstruction? left, [NotNullWhen(true)] out ILInstruction? right)
{
var op = this as BinaryNumericInstruction;
if (op != null)

13
ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -40,7 +41,7 @@ namespace ICSharpCode.Decompiler.IL @@ -40,7 +41,7 @@ namespace ICSharpCode.Decompiler.IL
partial class Nop
{
public string Comment;
public string? Comment;
public NopKind Kind;
@ -61,10 +62,10 @@ namespace ICSharpCode.Decompiler.IL @@ -61,10 +62,10 @@ namespace ICSharpCode.Decompiler.IL
partial class InvalidBranch : SimpleInstruction
{
public string Message;
public string? Message;
public StackType ExpectedResultType = StackType.Void;
public InvalidBranch(string message) : this()
public InvalidBranch(string? message) : this()
{
this.Message = message;
}
@ -88,10 +89,10 @@ namespace ICSharpCode.Decompiler.IL @@ -88,10 +89,10 @@ namespace ICSharpCode.Decompiler.IL
partial class InvalidExpression : SimpleInstruction
{
public string Message;
public string? Message;
public StackType ExpectedResultType = StackType.Unknown;
public InvalidExpression(string message) : this()
public InvalidExpression(string? message) : this()
{
this.Message = message;
}

7
ICSharpCode.Decompiler/IL/Instructions/StLoc.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -38,8 +39,8 @@ namespace ICSharpCode.Decompiler.IL @@ -38,8 +39,8 @@ namespace ICSharpCode.Decompiler.IL
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function));
Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable);
Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function!));
Debug.Assert(phase <= ILPhase.InILReader || variable.Function!.Variables[variable.IndexInFunction] == variable);
Debug.Assert(value.ResultType == variable.StackType);
}
}

13
ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2017 Siegfried Pammer
#nullable enable
// Copyright (c) 2017 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -23,23 +24,23 @@ namespace ICSharpCode.Decompiler.IL @@ -23,23 +24,23 @@ namespace ICSharpCode.Decompiler.IL
{
partial class StringToInt
{
public List<(string Key, int Value)> Map { get; }
public List<(string? Key, int Value)> Map { get; }
public StringToInt(ILInstruction argument, List<(string Key, int Value)> map)
public StringToInt(ILInstruction argument, List<(string? Key, int Value)> map)
: base(OpCode.StringToInt)
{
this.Argument = argument;
this.Map = map;
}
public StringToInt(ILInstruction argument, string[] map)
public StringToInt(ILInstruction argument, string?[] map)
: this(argument, ArrayToDictionary(map))
{
}
static List<(string Key, int Value)> ArrayToDictionary(string[] map)
static List<(string? Key, int Value)> ArrayToDictionary(string?[] map)
{
var dict = new List<(string Key, int Value)>();
var dict = new List<(string? Key, int Value)>();
for (int i = 0; i < map.Length; i++)
{
dict.Add((map[i], i));

4
ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
#nullable enable
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
@ -16,7 +17,6 @@ @@ -16,7 +17,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics;
using System.Linq;
@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.IL @@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.IL
this.Sections = new InstructionCollection<SwitchSection>(this, 1);
}
ILInstruction value;
ILInstruction value = null!;
public ILInstruction Value {
get { return this.value; }
set {

11
ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -33,7 +34,7 @@ namespace ICSharpCode.Decompiler.IL @@ -33,7 +34,7 @@ namespace ICSharpCode.Decompiler.IL
this.TryBlock = tryBlock;
}
ILInstruction tryBlock;
ILInstruction tryBlock = null!;
public ILInstruction TryBlock {
get { return this.tryBlock; }
set {
@ -144,7 +145,7 @@ namespace ICSharpCode.Decompiler.IL @@ -144,7 +145,7 @@ namespace ICSharpCode.Decompiler.IL
base.CheckInvariant(phase);
Debug.Assert(Parent is TryCatch);
Debug.Assert(filter.ResultType == StackType.I4);
Debug.Assert(this.IsDescendantOf(variable.Function));
Debug.Assert(this.IsDescendantOf(variable.Function!));
}
public override StackType ResultType {
@ -202,7 +203,7 @@ namespace ICSharpCode.Decompiler.IL @@ -202,7 +203,7 @@ namespace ICSharpCode.Decompiler.IL
this.FinallyBlock = finallyBlock;
}
ILInstruction finallyBlock;
ILInstruction finallyBlock = null!;
public ILInstruction FinallyBlock {
get { return this.finallyBlock; }
set {
@ -299,7 +300,7 @@ namespace ICSharpCode.Decompiler.IL @@ -299,7 +300,7 @@ namespace ICSharpCode.Decompiler.IL
this.FaultBlock = faultBlock;
}
ILInstruction faultBlock;
ILInstruction faultBlock = null!;
public ILInstruction FaultBlock {
get { return this.faultBlock; }
set {

3
ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

3
ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2017 Siegfried Pammer
#nullable enable
// Copyright (c) 2017 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

16
ICSharpCode.Decompiler/IL/Patterns/AnyNode.cs

@ -1,8 +1,5 @@ @@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
#nullable enable
using System;
namespace ICSharpCode.Decompiler.IL.Patterns
{
@ -37,19 +34,20 @@ namespace ICSharpCode.Decompiler.IL.Patterns @@ -37,19 +34,20 @@ namespace ICSharpCode.Decompiler.IL.Patterns
partial class AnyNode : PatternInstruction
{
CaptureGroup group;
CaptureGroup? group;
public AnyNode(CaptureGroup group = null)
public AnyNode(CaptureGroup? group = null)
: base(OpCode.AnyNode)
{
this.group = group;
}
protected internal override bool PerformMatch(ILInstruction other, ref Match match)
protected internal override bool PerformMatch(ILInstruction? other, ref Match match)
{
if (other == null)
return false;
match.Add(group, other);
if (group != null)
match.Add(group, other);
return true;
}
}

13
ICSharpCode.Decompiler/IL/Patterns/ListMatch.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2016 Daniel Grunwald
#nullable enable
// Copyright (c) 2016 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -44,7 +45,7 @@ namespace ICSharpCode.Decompiler.IL.Patterns @@ -44,7 +45,7 @@ namespace ICSharpCode.Decompiler.IL.Patterns
/// If the method returns true, it adds the capture groups (if any) to the match.
/// If the method returns false, the match object remains in a partially-updated state and needs to be restored
/// before it can be reused.</returns>
internal static bool DoMatch(IReadOnlyList<ILInstruction> patterns, IReadOnlyList<ILInstruction> syntaxList, ref Match match)
internal static bool DoMatch(IReadOnlyList<ILInstruction> patterns, IReadOnlyList<ILInstruction?> syntaxList, ref Match match)
{
ListMatch listMatch = new ListMatch(syntaxList);
do
@ -107,14 +108,14 @@ namespace ICSharpCode.Decompiler.IL.Patterns @@ -107,14 +108,14 @@ namespace ICSharpCode.Decompiler.IL.Patterns
/// <summary>
/// The syntax list we are matching against.
/// </summary>
internal readonly IReadOnlyList<ILInstruction> SyntaxList;
internal readonly IReadOnlyList<ILInstruction?> SyntaxList;
/// <summary>
/// The current index in the syntax list.
/// </summary>
internal int SyntaxIndex;
ListMatch(IReadOnlyList<ILInstruction> syntaxList)
ListMatch(IReadOnlyList<ILInstruction?> syntaxList)
{
this.SyntaxList = syntaxList;
this.SyntaxIndex = 0;
@ -122,8 +123,8 @@ namespace ICSharpCode.Decompiler.IL.Patterns @@ -122,8 +123,8 @@ namespace ICSharpCode.Decompiler.IL.Patterns
this.restoreStack = null;
}
List<SavePoint> backtrackingStack;
Stack<int> restoreStack;
List<SavePoint>? backtrackingStack;
Stack<int>? restoreStack;
void AddSavePoint(SavePoint savepoint)
{

5
ICSharpCode.Decompiler/IL/Patterns/Match.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2016 Daniel Grunwald
#nullable enable
// Copyright (c) 2016 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -33,7 +34,7 @@ namespace ICSharpCode.Decompiler.IL.Patterns @@ -33,7 +34,7 @@ namespace ICSharpCode.Decompiler.IL.Patterns
{
static readonly List<KeyValuePair<CaptureGroup, ILInstruction>> emptyResults = new List<KeyValuePair<CaptureGroup, ILInstruction>>();
List<KeyValuePair<CaptureGroup, ILInstruction>> results;
List<KeyValuePair<CaptureGroup, ILInstruction>>? results;
/// <summary>
/// Gets whether the match was successful.

3
ICSharpCode.Decompiler/IL/PrimitiveType.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2014 Daniel Grunwald
#nullable enable
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

4
ICSharpCode.Decompiler/IL/SemanticHelper.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System.Linq;
using ICSharpCode.Decompiler.Util;
@ -89,4 +91,4 @@ namespace ICSharpCode.Decompiler.IL @@ -89,4 +91,4 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
}
}
}

1
ICSharpCode.Decompiler/IL/SlotInfo.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
namespace ICSharpCode.Decompiler.IL
{

1
ICSharpCode.Decompiler/IL/StackType.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
namespace ICSharpCode.Decompiler.IL
{

3
ICSharpCode.Decompiler/IL/Transforms/FixLoneIsInst.cs

@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
@ -63,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -63,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
// Use extraction to turn isInst.Argument into a pure instruction, thus making the emulation possible
context.Step("FixLoneIsInst", isInst);
isInst.Argument.Extract();
isInst.Argument.Extract(context);
}
}
}

3
ICSharpCode.Decompiler/IL/Transforms/FixRemainingIncrements.cs

@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@ -73,7 +72,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -73,7 +72,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
else
{
context.Step($"Fix {call.Method.Name} call at 0x{call.StartILOffset:x4} using new local", call);
var newVariable = call.Arguments[0].Extract();
var newVariable = call.Arguments[0].Extract(context);
if (newVariable == null)
{
Debug.Fail("Failed to extract argument of remaining increment/decrement");

17
ICSharpCode.Decompiler/IL/Transforms/ILExtraction.cs

@ -21,6 +21,8 @@ using System.Collections.Generic; @@ -21,6 +21,8 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL.Transforms
{
/// <summary>
@ -33,6 +35,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -33,6 +35,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
readonly ILFunction Function;
readonly ILTransformContext context;
/// <summary>
/// Combined flags of all instructions being moved.
/// </summary>
@ -47,17 +51,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -47,17 +51,19 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
readonly List<Func<ILInstruction>> MoveActions = new List<Func<ILInstruction>>();
ExtractionContext(ILFunction function)
ExtractionContext(ILFunction function, ILTransformContext context)
{
Debug.Assert(function != null);
this.Function = function;
this.context = context;
}
internal void RegisterMove(ILInstruction predecessor)
{
FlagsBeingMoved |= predecessor.Flags;
MoveActions.Add(delegate {
var v = Function.RegisterVariable(VariableKind.StackSlot, predecessor.ResultType);
var type = context.TypeSystem.FindType(predecessor.ResultType.ToKnownTypeCode());
var v = Function.RegisterVariable(VariableKind.StackSlot, type);
predecessor.ReplaceWith(new LdLoc(v));
return new StLoc(v, predecessor);
});
@ -91,10 +97,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -91,10 +97,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
///
/// May return null if extraction is not possible.
/// </summary>
public static ILVariable Extract(ILInstruction instToExtract)
public static ILVariable Extract(ILInstruction instToExtract, ILTransformContext context)
{
var function = instToExtract.Ancestors.OfType<ILFunction>().First();
ExtractionContext ctx = new ExtractionContext(function);
ExtractionContext ctx = new ExtractionContext(function, context);
ctx.FlagsBeingMoved = instToExtract.Flags;
ILInstruction inst = instToExtract;
while (inst != null)
@ -113,8 +119,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -113,8 +119,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
// We've reached the target block, and extraction is possible all the way.
int insertIndex = inst.ChildIndex;
var type = context.TypeSystem.FindType(instToExtract.ResultType.ToKnownTypeCode());
// Move instToExtract itself:
var v = function.RegisterVariable(VariableKind.StackSlot, instToExtract.ResultType);
var v = function.RegisterVariable(VariableKind.StackSlot, type);
instToExtract.ReplaceWith(new LdLoc(v));
block.Instructions.Insert(insertIndex, new StLoc(v, instToExtract));
// Apply the other move actions:

8
ICSharpCode.Decompiler/IL/Transforms/NamedArgumentTransform.cs

@ -1,8 +1,5 @@ @@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics;
using System.Linq;
using System.Text;
using ICSharpCode.Decompiler.TypeSystem;
@ -90,7 +87,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -90,7 +87,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
var call = (CallInstruction)arg.Parent;
Debug.Assert(context.Function == call.Ancestors.OfType<ILFunction>().First());
var v = context.Function.RegisterVariable(VariableKind.NamedArgument, arg.ResultType);
var type = context.TypeSystem.FindType(arg.ResultType.ToKnownTypeCode());
var v = context.Function.RegisterVariable(VariableKind.NamedArgument, type);
context.Step($"Introduce named argument '{v.Name}'", arg);
if (!(call.Parent is Block namedArgBlock) || namedArgBlock.Kind != BlockKind.CallWithNamedArgs)
{

2
ICSharpCode.Decompiler/IL/Transforms/TransformArrayInitializers.cs

@ -257,7 +257,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -257,7 +257,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var otherLoadOfV = v.LoadInstructions.FirstOrDefault(l => !(l.Parent is Cpblk));
if (otherLoadOfV == null)
return false;
finalStore = otherLoadOfV.Parent.Extract();
finalStore = otherLoadOfV.Parent.Extract(context);
if (finalStore == null)
return false;
value = ((StLoc)finalStore.StoreInstructions[0]).Value;

6
ICSharpCode.Decompiler/TypeSystem/IMember.cs

@ -62,6 +62,12 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -62,6 +62,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
IType ReturnType { get; }
/// <summary>
/// Gets/Sets the declaring type (incl. type arguments, if any).
/// If this is not a specialized member, the value returned is equal to <see cref="IEntity.DeclaringTypeDefinition"/>.
/// </summary>
new IType DeclaringType { get; }
/// <summary>
/// Gets the interface members explicitly implemented by this member.
/// </summary>

2
ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs

@ -92,7 +92,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -92,7 +92,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
TypeParameterSubstitution IMember.Substitution => underlyingMethod.Substitution;
EntityHandle IEntity.MetadataToken => underlyingMethod.MetadataToken;
public string Name => underlyingMethod.Name;
IType IEntity.DeclaringType => underlyingMethod.DeclaringType;
public IType DeclaringType => underlyingMethod.DeclaringType;
ITypeDefinition IEntity.DeclaringTypeDefinition => underlyingMethod.DeclaringTypeDefinition;
IModule IEntity.ParentModule => underlyingMethod.ParentModule;
Accessibility IEntity.Accessibility => underlyingMethod.Accessibility;

1
ICSharpCode.Decompiler/Util/BitSet.cs

@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System;
using System.Diagnostics;

13
ICSharpCode.Decompiler/Util/BusyManager.cs

@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System;
using System.Collections.Generic;
@ -36,9 +37,9 @@ namespace ICSharpCode.Decompiler.Util @@ -36,9 +37,9 @@ namespace ICSharpCode.Decompiler.Util
{
public static readonly BusyLock Failed = new BusyLock(null);
readonly List<object> objectList;
readonly List<object?>? objectList;
internal BusyLock(List<object> objectList)
internal BusyLock(List<object?>? objectList)
{
this.objectList = objectList;
}
@ -56,13 +57,13 @@ namespace ICSharpCode.Decompiler.Util @@ -56,13 +57,13 @@ namespace ICSharpCode.Decompiler.Util
}
}
[ThreadStatic] static List<object> _activeObjects;
[ThreadStatic] static List<object?>? _activeObjects;
public static BusyLock Enter(object obj)
public static BusyLock Enter(object? obj)
{
List<object> activeObjects = _activeObjects;
List<object?>? activeObjects = _activeObjects;
if (activeObjects == null)
activeObjects = _activeObjects = new List<object>();
activeObjects = _activeObjects = new List<object?>();
for (int i = 0; i < activeObjects.Count; i++)
{
if (activeObjects[i] == obj)

2
ICSharpCode.Decompiler/Util/CacheManager.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System;
using System.Collections.Concurrent;

6
ICSharpCode.Decompiler/Util/CallbackOnDispose.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System;
using System.Threading;
@ -30,7 +32,7 @@ namespace ICSharpCode.Decompiler.Util @@ -30,7 +32,7 @@ namespace ICSharpCode.Decompiler.Util
/// </remarks>
public sealed class CallbackOnDispose : IDisposable
{
Action action;
Action? action;
public CallbackOnDispose(Action action)
{
@ -41,7 +43,7 @@ namespace ICSharpCode.Decompiler.Util @@ -41,7 +43,7 @@ namespace ICSharpCode.Decompiler.Util
public void Dispose()
{
Action a = Interlocked.Exchange(ref action, null);
Action? a = Interlocked.Exchange(ref action, null);
if (a != null)
{
a();

35
ICSharpCode.Decompiler/Util/CollectionExtensions.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System;
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
@ -14,13 +15,13 @@ namespace ICSharpCode.Decompiler.Util @@ -14,13 +15,13 @@ namespace ICSharpCode.Decompiler.Util
}
#if !NETCORE
public static IEnumerable<(A, B)> Zip<A, B>(this IEnumerable<A> input1, IEnumerable<B> input2)
public static IEnumerable<(A, B)> Zip<A, B>(this IEnumerable<A>? input1, IEnumerable<B>? input2)
{
return input1.Zip(input2, (a, b) => (a, b));
}
#endif
public static IEnumerable<(A, B)> ZipLongest<A, B>(this IEnumerable<A> input1, IEnumerable<B> input2)
public static IEnumerable<(A?, B?)> ZipLongest<A, B>(this IEnumerable<A> input1, IEnumerable<B> input2)
{
using (var it1 = input1.GetEnumerator())
{
@ -60,7 +61,7 @@ namespace ICSharpCode.Decompiler.Util @@ -60,7 +61,7 @@ namespace ICSharpCode.Decompiler.Util
}
#if !NETCORE
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> input)
public static HashSet<T> ToHashSet<T>(this IEnumerable<T>? input)
{
return new HashSet<T>(input);
}
@ -76,14 +77,14 @@ namespace ICSharpCode.Decompiler.Util @@ -76,14 +77,14 @@ namespace ICSharpCode.Decompiler.Util
return input.Skip(input.Count - count);
}
public static T PopOrDefault<T>(this Stack<T> stack)
public static T? PopOrDefault<T>(this Stack<T> stack)
{
if (stack.Count == 0)
return default(T);
return stack.Pop();
}
public static T PeekOrDefault<T>(this Stack<T> stack)
public static T? PeekOrDefault<T>(this Stack<T> stack)
{
if (stack.Count == 0)
return default(T);
@ -277,7 +278,7 @@ namespace ICSharpCode.Decompiler.Util @@ -277,7 +278,7 @@ namespace ICSharpCode.Decompiler.Util
/// Returns the minimum element.
/// </summary>
/// <exception cref="InvalidOperationException">The input sequence is empty</exception>
public static T MinBy<T, K>(this IEnumerable<T> source, Func<T, K> keySelector, IComparer<K> keyComparer)
public static T MinBy<T, K>(this IEnumerable<T> source, Func<T, K> keySelector, IComparer<K>? keyComparer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
@ -318,7 +319,7 @@ namespace ICSharpCode.Decompiler.Util @@ -318,7 +319,7 @@ namespace ICSharpCode.Decompiler.Util
/// Returns the maximum element.
/// </summary>
/// <exception cref="InvalidOperationException">The input sequence is empty</exception>
public static T MaxBy<T, K>(this IEnumerable<T> source, Func<T, K> keySelector, IComparer<K> keyComparer)
public static T MaxBy<T, K>(this IEnumerable<T> source, Func<T, K> keySelector, IComparer<K>? keyComparer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
@ -353,12 +354,12 @@ namespace ICSharpCode.Decompiler.Util @@ -353,12 +354,12 @@ namespace ICSharpCode.Decompiler.Util
list.RemoveAt(list.Count - 1);
}
public static T OnlyOrDefault<T>(this IEnumerable<T> source, Func<T, bool> predicate) => OnlyOrDefault(source.Where(predicate));
public static T? OnlyOrDefault<T>(this IEnumerable<T>? source, Func<T, bool>? predicate) => OnlyOrDefault(source.Where(predicate));
public static T OnlyOrDefault<T>(this IEnumerable<T> source)
public static T? OnlyOrDefault<T>(this IEnumerable<T> source)
{
bool any = false;
T first = default;
T? first = default;
foreach (var t in source)
{
if (any)
@ -372,14 +373,14 @@ namespace ICSharpCode.Decompiler.Util @@ -372,14 +373,14 @@ namespace ICSharpCode.Decompiler.Util
#region Aliases/shortcuts for Enumerable extension methods
public static bool Any<T>(this ICollection<T> list) => list.Count > 0;
public static bool Any<T>(this T[] array, Predicate<T> match) => Array.Exists(array, match);
public static bool Any<T>(this List<T> list, Predicate<T> match) => list.Exists(match);
public static bool Any<T>(this T[]? array, Predicate<T>? match) => Array.Exists(array, match);
public static bool Any<T>(this List<T> list, Predicate<T>? match) => list.Exists(match);
public static bool All<T>(this T[] array, Predicate<T> match) => Array.TrueForAll(array, match);
public static bool All<T>(this List<T> list, Predicate<T> match) => list.TrueForAll(match);
public static bool All<T>(this T[]? array, Predicate<T>? match) => Array.TrueForAll(array, match);
public static bool All<T>(this List<T> list, Predicate<T>? match) => list.TrueForAll(match);
public static T FirstOrDefault<T>(this T[] array, Predicate<T> predicate) => Array.Find(array, predicate);
public static T FirstOrDefault<T>(this List<T> list, Predicate<T> predicate) => list.Find(predicate);
public static T FirstOrDefault<T>(this T[]? array, Predicate<T>? predicate) => Array.Find(array, predicate);
public static T FirstOrDefault<T>(this List<T> list, Predicate<T>? predicate) => list.Find(predicate);
public static T Last<T>(this IList<T> list) => list[list.Count - 1];
#endregion

5
ICSharpCode.Decompiler/Util/EmptyList.cs

@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System;
using System.Collections;
@ -91,11 +92,11 @@ namespace ICSharpCode.Decompiler.Util @@ -91,11 +92,11 @@ namespace ICSharpCode.Decompiler.Util
}
T IEnumerator<T>.Current {
get { return default(T); }
get { throw new NotSupportedException(); }
}
object IEnumerator.Current {
get { return default(T); }
get { throw new NotSupportedException(); }
}
void IDisposable.Dispose()

5
ICSharpCode.Decompiler/Util/ExtensionMethods.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
#nullable enable
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -26,7 +27,7 @@ namespace ICSharpCode.Decompiler.Util @@ -26,7 +27,7 @@ namespace ICSharpCode.Decompiler.Util
/// </summary>
static class ExtensionMethods
{
public static Predicate<T> And<T>(this Predicate<T> filter1, Predicate<T> filter2)
public static Predicate<T>? And<T>(this Predicate<T>? filter1, Predicate<T>? filter2)
{
if (filter1 == null)
return filter2;

24
ICSharpCode.Decompiler/Util/FileUtility.cs

@ -16,7 +16,10 @@ @@ -16,7 +16,10 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
@ -28,9 +31,10 @@ namespace ICSharpCode.Decompiler.Util @@ -28,9 +31,10 @@ namespace ICSharpCode.Decompiler.Util
/// Gets the normalized version of fileName.
/// Slashes are replaced with backslashes, backreferences "." and ".." are 'evaluated'.
/// </summary>
public static string NormalizePath(string fileName)
[return: NotNullIfNotNull("fileName")]
public static string? NormalizePath(string? fileName)
{
if (string.IsNullOrEmpty(fileName))
if (fileName == null || fileName.Length == 0)
return fileName;
int i;
@ -169,14 +173,14 @@ namespace ICSharpCode.Decompiler.Util @@ -169,14 +173,14 @@ namespace ICSharpCode.Decompiler.Util
&& (fileName[1] == '\\' || fileName[1] == '/');
}
public static bool IsEqualFileName(string fileName1, string fileName2)
public static bool IsEqualFileName(string? fileName1, string? fileName2)
{
return string.Equals(NormalizePath(fileName1),
NormalizePath(fileName2),
StringComparison.OrdinalIgnoreCase);
}
public static bool IsBaseDirectory(string baseDirectory, string testDirectory)
public static bool IsBaseDirectory(string? baseDirectory, string? testDirectory)
{
if (baseDirectory == null || testDirectory == null)
return false;
@ -189,9 +193,10 @@ namespace ICSharpCode.Decompiler.Util @@ -189,9 +193,10 @@ namespace ICSharpCode.Decompiler.Util
return testDirectory.StartsWith(baseDirectory, StringComparison.OrdinalIgnoreCase);
}
static string AddTrailingSeparator(string input)
[return: NotNullIfNotNull("input")]
static string? AddTrailingSeparator(string? input)
{
if (string.IsNullOrEmpty(input))
if (input == null || input.Length == 0)
return input;
if (input[input.Length - 1] == Path.DirectorySeparatorChar || input[input.Length - 1] == Path.AltDirectorySeparatorChar)
return input;
@ -212,9 +217,9 @@ namespace ICSharpCode.Decompiler.Util @@ -212,9 +217,9 @@ namespace ICSharpCode.Decompiler.Util
/// Converts a given absolute path and a given base path to a path that leads
/// from the base path to the absoulte path. (as a relative path)
/// </summary>
public static string GetRelativePath(string baseDirectoryPath, string absPath)
public static string GetRelativePath(string? baseDirectoryPath, string absPath)
{
if (string.IsNullOrEmpty(baseDirectoryPath))
if (baseDirectoryPath == null || baseDirectoryPath.Length == 0)
{
return absPath;
}
@ -252,7 +257,8 @@ namespace ICSharpCode.Decompiler.Util @@ -252,7 +257,8 @@ namespace ICSharpCode.Decompiler.Util
return erg.ToString();
}
public static string TrimPath(string path, int max_chars)
[return: NotNullIfNotNull("path")]
public static string? TrimPath(string? path, int max_chars)
{
const char ellipsis = '\u2026'; // HORIZONTAL ELLIPSIS
const int ellipsisLength = 2;

26
ICSharpCode.Decompiler/Util/GraphVizGraph.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
@ -34,8 +36,8 @@ namespace ICSharpCode.Decompiler.Util @@ -34,8 +36,8 @@ namespace ICSharpCode.Decompiler.Util
List<GraphVizNode> nodes = new List<GraphVizNode>();
List<GraphVizEdge> edges = new List<GraphVizEdge>();
public string rankdir;
public string Title;
public string? rankdir;
public string? Title;
public void AddEdge(GraphVizEdge edge)
{
@ -58,7 +60,7 @@ namespace ICSharpCode.Decompiler.Util @@ -58,7 +60,7 @@ namespace ICSharpCode.Decompiler.Util
Show(null);
}
public void Show(string name)
public void Show(string? name)
{
if (name == null)
name = Title;
@ -83,7 +85,7 @@ namespace ICSharpCode.Decompiler.Util @@ -83,7 +85,7 @@ namespace ICSharpCode.Decompiler.Util
}
}
static void WriteGraphAttribute(TextWriter writer, string name, string value)
static void WriteGraphAttribute(TextWriter writer, string name, string? value)
{
if (value != null)
writer.WriteLine("{0}={1};", name, Escape(value));
@ -105,7 +107,7 @@ namespace ICSharpCode.Decompiler.Util @@ -105,7 +107,7 @@ namespace ICSharpCode.Decompiler.Util
}
}
internal static void WriteAttribute(TextWriter writer, string name, string value, ref bool isFirst)
internal static void WriteAttribute(TextWriter writer, string name, string? value, ref bool isFirst)
{
if (value != null)
{
@ -141,13 +143,13 @@ namespace ICSharpCode.Decompiler.Util @@ -141,13 +143,13 @@ namespace ICSharpCode.Decompiler.Util
public readonly string Source, Target;
/// <summary>edge stroke color</summary>
public string color;
public string? color;
/// <summary>use edge to affect node ranking</summary>
public bool? constraint;
public string label;
public string? label;
public string style;
public string? style;
/// <summary>point size of label</summary>
public int? fontsize;
@ -184,9 +186,9 @@ namespace ICSharpCode.Decompiler.Util @@ -184,9 +186,9 @@ namespace ICSharpCode.Decompiler.Util
sealed class GraphVizNode
{
public readonly string ID;
public string label;
public string? label;
public string labelloc;
public string? labelloc;
/// <summary>point size of label</summary>
public int? fontsize;
@ -195,10 +197,10 @@ namespace ICSharpCode.Decompiler.Util @@ -195,10 +197,10 @@ namespace ICSharpCode.Decompiler.Util
public double? height;
/// <summary>space around label</summary>
public string margin;
public string? margin;
/// <summary>node shape</summary>
public string shape;
public string? shape;
public GraphVizNode(string id)
{

7
ICSharpCode.Decompiler/Util/Interval.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2016 Daniel Grunwald
#nullable enable
// Copyright (c) 2016 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -111,7 +112,7 @@ namespace ICSharpCode.Decompiler.Util @@ -111,7 +112,7 @@ namespace ICSharpCode.Decompiler.Util
}
#region Equals and GetHashCode implementation
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return (obj is Interval) && Equals((Interval)obj);
}
@ -281,7 +282,7 @@ namespace ICSharpCode.Decompiler.Util @@ -281,7 +282,7 @@ namespace ICSharpCode.Decompiler.Util
}
#region Equals and GetHashCode implementation
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return (obj is LongInterval) && Equals((LongInterval)obj);
}

3
ICSharpCode.Decompiler/Util/KeyComparer.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
#nullable enable
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

7
ICSharpCode.Decompiler/Util/LongSet.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2016 Daniel Grunwald
#nullable enable
// Copyright (c) 2016 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -82,7 +83,7 @@ namespace ICSharpCode.Decompiler.Util @@ -82,7 +83,7 @@ namespace ICSharpCode.Decompiler.Util
/// <summary>
/// Creates a new LongSet the contains the values from the specified intervals.
/// </summary>
public LongSet(IEnumerable<LongInterval> intervals)
public LongSet(IEnumerable<LongInterval>? intervals)
: this(MergeOverlapping(intervals.Where(i => !i.IsEmpty).OrderBy(i => i.Start)).ToImmutableArray())
{
}
@ -350,7 +351,7 @@ namespace ICSharpCode.Decompiler.Util @@ -350,7 +351,7 @@ namespace ICSharpCode.Decompiler.Util
}
#region Equals and GetHashCode implementation
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is LongSet && SetEquals((LongSet)obj);
}

5
ICSharpCode.Decompiler/Util/MultiDictionary.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
#nullable enable
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -33,7 +34,7 @@ namespace ICSharpCode.Decompiler.Util @@ -33,7 +34,7 @@ namespace ICSharpCode.Decompiler.Util
dict = new Dictionary<TKey, List<TValue>>();
}
public MultiDictionary(IEqualityComparer<TKey> comparer)
public MultiDictionary(IEqualityComparer<TKey>? comparer)
{
dict = new Dictionary<TKey, List<TValue>>(comparer);
}

8
ICSharpCode.Decompiler/Util/NullAttributes.cs

@ -25,5 +25,13 @@ namespace System.Diagnostics.CodeAnalysis @@ -25,5 +25,13 @@ namespace System.Diagnostics.CodeAnalysis
public bool ReturnValue { get; }
}
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class DoesNotReturnIfAttribute : Attribute
{
public DoesNotReturnIfAttribute(bool parameterValue) => ParameterValue = parameterValue;
public bool ParameterValue { get; }
}
}
#endif

3
ICSharpCode.Decompiler/Util/Platform.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
#nullable enable
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software

15
ICSharpCode.Decompiler/Util/ProjectedList.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
#nullable enable
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -25,7 +26,7 @@ namespace ICSharpCode.Decompiler.Util @@ -25,7 +26,7 @@ namespace ICSharpCode.Decompiler.Util
{
readonly IList<TInput> input;
readonly Func<TInput, TOutput> projection;
readonly TOutput[] items;
readonly TOutput?[] items;
public ProjectedList(IList<TInput> input, Func<TInput, TOutput> projection)
{
@ -35,12 +36,12 @@ namespace ICSharpCode.Decompiler.Util @@ -35,12 +36,12 @@ namespace ICSharpCode.Decompiler.Util
throw new ArgumentNullException(nameof(projection));
this.input = input;
this.projection = projection;
this.items = new TOutput[input.Count];
this.items = new TOutput?[input.Count];
}
public TOutput this[int index] {
get {
TOutput output = LazyInit.VolatileRead(ref items[index]);
TOutput? output = LazyInit.VolatileRead(ref items[index]);
if (output != null)
{
return output;
@ -72,7 +73,7 @@ namespace ICSharpCode.Decompiler.Util @@ -72,7 +73,7 @@ namespace ICSharpCode.Decompiler.Util
readonly IList<TInput> input;
readonly TContext context;
readonly Func<TContext, TInput, TOutput> projection;
readonly TOutput[] items;
readonly TOutput?[] items;
public ProjectedList(TContext context, IList<TInput> input, Func<TContext, TInput, TOutput> projection)
{
@ -83,12 +84,12 @@ namespace ICSharpCode.Decompiler.Util @@ -83,12 +84,12 @@ namespace ICSharpCode.Decompiler.Util
this.input = input;
this.context = context;
this.projection = projection;
this.items = new TOutput[input.Count];
this.items = new TOutput?[input.Count];
}
public TOutput this[int index] {
get {
TOutput output = LazyInit.VolatileRead(ref items[index]);
TOutput? output = LazyInit.VolatileRead(ref items[index]);
if (output != null)
{
return output;

7
ICSharpCode.Decompiler/Util/ReferenceComparer.cs

@ -15,22 +15,23 @@ @@ -15,22 +15,23 @@
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace ICSharpCode.Decompiler.Util
{
public sealed class ReferenceComparer : IEqualityComparer<object>
public sealed class ReferenceComparer : IEqualityComparer<object?>
{
public readonly static ReferenceComparer Instance = new ReferenceComparer();
public new bool Equals(object x, object y)
public new bool Equals(object? x, object? y)
{
return x == y;
}
public int GetHashCode(object obj)
public int GetHashCode(object? obj)
{
return RuntimeHelpers.GetHashCode(obj);
}

27
ICSharpCode.Decompiler/Util/ResourcesFile.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2018 Daniel Grunwald
#nullable enable
// Copyright (c) 2018 Daniel Grunwald
// Based on the .NET Core ResourceReader; make available under the MIT license
// by the .NET Foundation.
//
@ -30,7 +31,7 @@ namespace ICSharpCode.Decompiler.Util @@ -30,7 +31,7 @@ namespace ICSharpCode.Decompiler.Util
/// <summary>
/// .resources file.
/// </summary>
public class ResourcesFile : IEnumerable<KeyValuePair<string, object>>, IDisposable
public class ResourcesFile : IEnumerable<KeyValuePair<string, object?>>, IDisposable
{
sealed class MyBinaryReader : BinaryReader
{
@ -87,7 +88,7 @@ namespace ICSharpCode.Decompiler.Util @@ -87,7 +88,7 @@ namespace ICSharpCode.Decompiler.Util
readonly long fileStartPosition;
readonly long nameSectionPosition;
readonly long dataSectionPosition;
long[] startPositions;
long[]? startPositions;
/// <summary>
/// Creates a new ResourcesFile.
@ -285,7 +286,7 @@ namespace ICSharpCode.Decompiler.Util @@ -285,7 +286,7 @@ namespace ICSharpCode.Decompiler.Util
return true;
}
object LoadObject(int dataOffset)
object? LoadObject(int dataOffset)
{
try
{
@ -318,7 +319,7 @@ namespace ICSharpCode.Decompiler.Util @@ -318,7 +319,7 @@ namespace ICSharpCode.Decompiler.Util
// from that location.
// Anyone who calls LoadObject should make sure they take a lock so
// no one can cause us to do a seek in here.
private object LoadObjectV1(int dataOffset)
private object? LoadObjectV1(int dataOffset)
{
Debug.Assert(System.Threading.Monitor.IsEntered(reader));
reader.Seek(dataSectionPosition + dataOffset, SeekOrigin.Begin);
@ -372,7 +373,7 @@ namespace ICSharpCode.Decompiler.Util @@ -372,7 +373,7 @@ namespace ICSharpCode.Decompiler.Util
}
}
private object LoadObjectV2(int dataOffset)
private object? LoadObjectV2(int dataOffset)
{
Debug.Assert(System.Threading.Monitor.IsEntered(reader));
reader.Seek(dataSectionPosition + dataOffset, SeekOrigin.Begin);
@ -464,19 +465,19 @@ namespace ICSharpCode.Decompiler.Util @@ -464,19 +465,19 @@ namespace ICSharpCode.Decompiler.Util
}
}
public object GetResourceValue(int index)
public object? GetResourceValue(int index)
{
GetResourceName(index, out int dataOffset);
return LoadObject(dataOffset);
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
public IEnumerator<KeyValuePair<string, object?>> GetEnumerator()
{
for (int i = 0; i < numResources; i++)
{
string name = GetResourceName(i, out int dataOffset);
object val = LoadObject(dataOffset);
yield return new KeyValuePair<string, object>(name, val);
object? val = LoadObject(dataOffset);
yield return new KeyValuePair<string, object?>(name, val);
}
}
@ -487,7 +488,7 @@ namespace ICSharpCode.Decompiler.Util @@ -487,7 +488,7 @@ namespace ICSharpCode.Decompiler.Util
long[] GetStartPositions()
{
long[] positions = LazyInit.VolatileRead(ref startPositions);
long[]? positions = LazyInit.VolatileRead(ref startPositions);
if (positions != null)
return positions;
lock (reader)
@ -541,11 +542,11 @@ namespace ICSharpCode.Decompiler.Util @@ -541,11 +542,11 @@ namespace ICSharpCode.Decompiler.Util
public class ResourceSerializedObject
{
public string TypeName { get; }
public string? TypeName { get; }
readonly ResourcesFile file;
readonly long position;
internal ResourceSerializedObject(string typeName, ResourcesFile file, long position)
internal ResourceSerializedObject(string? typeName, ResourcesFile file, long position)
{
this.TypeName = typeName;
this.file = file;

15
ICSharpCode.Decompiler/Util/TreeTraversal.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
#nullable enable
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -32,7 +33,7 @@ namespace ICSharpCode.Decompiler.Util @@ -32,7 +33,7 @@ namespace ICSharpCode.Decompiler.Util
/// <param name="root">The root element of the tree.</param>
/// <param name="recursion">The function that gets the children of an element.</param>
/// <returns>Iterator that enumerates the tree structure in pre-order.</returns>
public static IEnumerable<T> PreOrder<T>(T root, Func<T, IEnumerable<T>> recursion)
public static IEnumerable<T> PreOrder<T>(T root, Func<T, IEnumerable<T>?> recursion)
{
return PreOrder(new T[] { root }, recursion);
}
@ -43,7 +44,7 @@ namespace ICSharpCode.Decompiler.Util @@ -43,7 +44,7 @@ namespace ICSharpCode.Decompiler.Util
/// <param name="input">The root elements of the forest.</param>
/// <param name="recursion">The function that gets the children of an element.</param>
/// <returns>Iterator that enumerates the tree structure in pre-order.</returns>
public static IEnumerable<T> PreOrder<T>(IEnumerable<T> input, Func<T, IEnumerable<T>> recursion)
public static IEnumerable<T> PreOrder<T>(IEnumerable<T> input, Func<T, IEnumerable<T>?> recursion)
{
Stack<IEnumerator<T>> stack = new Stack<IEnumerator<T>>();
try
@ -55,7 +56,7 @@ namespace ICSharpCode.Decompiler.Util @@ -55,7 +56,7 @@ namespace ICSharpCode.Decompiler.Util
{
T element = stack.Peek().Current;
yield return element;
IEnumerable<T> children = recursion(element);
IEnumerable<T>? children = recursion(element);
if (children != null)
{
stack.Push(children.GetEnumerator());
@ -79,7 +80,7 @@ namespace ICSharpCode.Decompiler.Util @@ -79,7 +80,7 @@ namespace ICSharpCode.Decompiler.Util
/// <param name="root">The root element of the tree.</param>
/// <param name="recursion">The function that gets the children of an element.</param>
/// <returns>Iterator that enumerates the tree structure in post-order.</returns>
public static IEnumerable<T> PostOrder<T>(T root, Func<T, IEnumerable<T>> recursion)
public static IEnumerable<T> PostOrder<T>(T root, Func<T, IEnumerable<T>?> recursion)
{
return PostOrder(new T[] { root }, recursion);
}
@ -90,7 +91,7 @@ namespace ICSharpCode.Decompiler.Util @@ -90,7 +91,7 @@ namespace ICSharpCode.Decompiler.Util
/// <param name="input">The root elements of the forest.</param>
/// <param name="recursion">The function that gets the children of an element.</param>
/// <returns>Iterator that enumerates the tree structure in post-order.</returns>
public static IEnumerable<T> PostOrder<T>(IEnumerable<T> input, Func<T, IEnumerable<T>> recursion)
public static IEnumerable<T> PostOrder<T>(IEnumerable<T> input, Func<T, IEnumerable<T>?> recursion)
{
Stack<IEnumerator<T>> stack = new Stack<IEnumerator<T>>();
try
@ -101,7 +102,7 @@ namespace ICSharpCode.Decompiler.Util @@ -101,7 +102,7 @@ namespace ICSharpCode.Decompiler.Util
while (stack.Peek().MoveNext())
{
T element = stack.Peek().Current;
IEnumerable<T> children = recursion(element);
IEnumerable<T>? children = recursion(element);
if (children != null)
{
stack.Push(children.GetEnumerator());

7
ICSharpCode.Decompiler/Util/UnicodeNewline.cs

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
#nullable enable
//
// UnicodeNewline.cs
//
@ -118,7 +119,7 @@ namespace ICSharpCode.Decompiler.Util @@ -118,7 +119,7 @@ namespace ICSharpCode.Decompiler.Util
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns>
/// <param name="curChar">The current character.</param>
/// <param name="nextChar">A callback getting the next character (may be null).</param>
public static int GetDelimiterLength(char curChar, Func<char> nextChar = null)
public static int GetDelimiterLength(char curChar, Func<char>? nextChar = null)
{
if (curChar == CR)
{
@ -161,7 +162,7 @@ namespace ICSharpCode.Decompiler.Util @@ -161,7 +162,7 @@ namespace ICSharpCode.Decompiler.Util
/// <param name = "length">The length of the delimiter</param>
/// <param name = "type">The type of the delimiter</param>
/// <param name="nextChar">A callback getting the next character (may be null).</param>
public static bool TryGetDelimiterLengthAndType(char curChar, out int length, out UnicodeNewline type, Func<char> nextChar = null)
public static bool TryGetDelimiterLengthAndType(char curChar, out int length, out UnicodeNewline type, Func<char>? nextChar = null)
{
if (curChar == CR)
{
@ -275,7 +276,7 @@ namespace ICSharpCode.Decompiler.Util @@ -275,7 +276,7 @@ namespace ICSharpCode.Decompiler.Util
/// <returns>0 == no new line, otherwise it returns either 1 or 2 depending of the length of the delimiter.</returns>
/// <param name="curChar">The current character.</param>
/// <param name="nextChar">A callback getting the next character (may be null).</param>
public static UnicodeNewline GetDelimiterType(char curChar, Func<char> nextChar = null)
public static UnicodeNewline GetDelimiterType(char curChar, Func<char>? nextChar = null)
{
switch (curChar)
{

14
ICSharpCode.Decompiler/Util/UnionFind.cs

@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System.Collections.Generic;
@ -32,6 +33,12 @@ namespace ICSharpCode.Decompiler.Util @@ -32,6 +33,12 @@ namespace ICSharpCode.Decompiler.Util
public int rank;
public Node parent;
public T value;
internal Node(T value)
{
this.value = value;
this.parent = this;
}
}
public UnionFind()
@ -44,10 +51,7 @@ namespace ICSharpCode.Decompiler.Util @@ -44,10 +51,7 @@ namespace ICSharpCode.Decompiler.Util
Node node;
if (!mapping.TryGetValue(element, out node))
{
node = new Node {
value = element,
rank = 0
};
node = new Node(element);
node.parent = node;
mapping.Add(element, node);
}
@ -84,5 +88,3 @@ namespace ICSharpCode.Decompiler.Util @@ -84,5 +88,3 @@ namespace ICSharpCode.Decompiler.Util
}
}
}

23
ICSharpCode.Decompiler/Util/Win32Resources.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System;
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection.PortableExecutable;
@ -15,21 +16,21 @@ namespace ICSharpCode.Decompiler.Util @@ -15,21 +16,21 @@ namespace ICSharpCode.Decompiler.Util
/// </summary>
/// <param name="pe"></param>
/// <returns></returns>
public static unsafe Win32ResourceDirectory ReadWin32Resources(this PEReader pe)
public static unsafe Win32ResourceDirectory? ReadWin32Resources(this PEReader pe)
{
if (pe == null)
{
throw new ArgumentNullException(nameof(pe));
}
int rva = pe.PEHeaders.PEHeader.ResourceTableDirectory.RelativeVirtualAddress;
int rva = pe.PEHeaders.PEHeader?.ResourceTableDirectory.RelativeVirtualAddress ?? 0;
if (rva == 0)
return null;
byte* pRoot = pe.GetSectionData(rva).Pointer;
return new Win32ResourceDirectory(pe, pRoot, 0, new Win32ResourceName("Root"));
}
public static Win32ResourceDirectory Find(this Win32ResourceDirectory root, Win32ResourceName type)
public static Win32ResourceDirectory? Find(this Win32ResourceDirectory root, Win32ResourceName type)
{
if (root is null)
throw new ArgumentNullException(nameof(root));
@ -41,7 +42,7 @@ namespace ICSharpCode.Decompiler.Util @@ -41,7 +42,7 @@ namespace ICSharpCode.Decompiler.Util
return root.FindDirectory(type);
}
public static Win32ResourceDirectory Find(this Win32ResourceDirectory root, Win32ResourceName type, Win32ResourceName name)
public static Win32ResourceDirectory? Find(this Win32ResourceDirectory root, Win32ResourceName type, Win32ResourceName name)
{
if (root is null)
throw new ArgumentNullException(nameof(root));
@ -55,7 +56,7 @@ namespace ICSharpCode.Decompiler.Util @@ -55,7 +56,7 @@ namespace ICSharpCode.Decompiler.Util
return root.FindDirectory(type)?.FindDirectory(name);
}
public static Win32ResourceData Find(this Win32ResourceDirectory root, Win32ResourceName type, Win32ResourceName name, Win32ResourceName langId)
public static Win32ResourceData? Find(this Win32ResourceDirectory root, Win32ResourceName type, Win32ResourceName name, Win32ResourceName langId)
{
if (root is null)
throw new ArgumentNullException(nameof(root));
@ -122,7 +123,7 @@ namespace ICSharpCode.Decompiler.Util @@ -122,7 +123,7 @@ namespace ICSharpCode.Decompiler.Util
return new string(pString->NameString, 0, pString->Length);
}
public Win32ResourceDirectory FindDirectory(Win32ResourceName name)
public Win32ResourceDirectory? FindDirectory(Win32ResourceName name)
{
foreach (var directory in Directories)
{
@ -132,7 +133,7 @@ namespace ICSharpCode.Decompiler.Util @@ -132,7 +133,7 @@ namespace ICSharpCode.Decompiler.Util
return null;
}
public Win32ResourceData FindData(Win32ResourceName name)
public Win32ResourceData? FindData(Win32ResourceName name)
{
foreach (var data in Datas)
{
@ -142,12 +143,12 @@ namespace ICSharpCode.Decompiler.Util @@ -142,12 +143,12 @@ namespace ICSharpCode.Decompiler.Util
return null;
}
public Win32ResourceDirectory FirstDirectory()
public Win32ResourceDirectory? FirstDirectory()
{
return Directories.Count != 0 ? Directories[0] : null;
}
public Win32ResourceData FirstData()
public Win32ResourceData? FirstData()
{
return Datas.Count != 0 ? Datas[0] : null;
}
@ -248,7 +249,7 @@ namespace ICSharpCode.Decompiler.Util @@ -248,7 +249,7 @@ namespace ICSharpCode.Decompiler.Util
return _name.GetHashCode();
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (!(obj is Win32ResourceName name))
return false;

4
ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
@ -112,4 +112,4 @@ @@ -112,4 +112,4 @@
<Page Include="Cases\Issue445.xaml" />
</ItemGroup>
</Project>
</Project>

Loading…
Cancel
Save