Browse Source

Replace AST null-objects with nullable reference types

With every optional slot nullable, the null-object pattern is dead. Generated
non-nullable getters return the backing field directly, which surfaced a last
tier of slots the decompiler legitimately leaves empty (omitted range operands,
an implicitly-typed array creation, unnamed parameters, an unbound generic
argument, and others) and flips them to nullable too. The machinery is then
removed entirely: the per-node null classes, the .Null statics and
VisitNullNode, AstNode.IsNull, the role null object, and Identifier.Null.
AcceptVisitor becomes unconditionally generated, and consumers move from
.IsNull to is null and from unconditional visits to ?.AcceptVisitor.
Assisted-by: Claude:claude-opus-4-8:Claude Code
pull/3807/head
Siegfried Pammer 3 weeks ago committed by Siegfried Pammer
parent
commit
9aa0ddd37b
  1. 59
      ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs
  2. 6
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 6
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  4. 4
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
  5. 46
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  6. 2
      ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs
  7. 2
      ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs
  8. 36
      ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs
  9. 4
      ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs
  10. 26
      ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs
  11. 4
      ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs
  12. 4
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs
  13. 12
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs
  14. 4
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ConditionalExpression.cs
  15. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InterpolatedStringExpression.cs
  16. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/LambdaExpression.cs
  17. 20
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs
  18. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/RecursivePatternExpression.cs
  19. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/StackAllocExpression.cs
  20. 4
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs
  21. 2
      ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerAstType.cs
  22. 2
      ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Attribute.cs
  23. 2
      ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/AttributeSection.cs
  24. 2
      ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/NamespaceDeclaration.cs
  25. 2
      ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingAliasDeclaration.cs
  26. 2
      ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingDeclaration.cs
  27. 4
      ICSharpCode.Decompiler/CSharp/Syntax/Identifier.cs
  28. 2
      ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs
  29. 2
      ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/AnyNode.cs
  30. 2
      ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/INode.cs
  31. 2
      ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/OptionalNode.cs
  32. 4
      ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Pattern.cs
  33. 2
      ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Repeat.cs
  34. 26
      ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs
  35. 2
      ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs
  36. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Statements/BlockStatement.cs
  37. 4
      ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForStatement.cs
  38. 4
      ICSharpCode.Decompiler/CSharp/Syntax/Statements/IfElseStatement.cs
  39. 6
      ICSharpCode.Decompiler/CSharp/Syntax/Statements/TryCatchStatement.cs
  40. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Statements/UsingStatement.cs
  41. 2
      ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs
  42. 2
      ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs
  43. 2
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/Accessor.cs
  44. 2
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ConstructorDeclaration.cs
  45. 4
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs
  46. 2
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EnumMemberDeclaration.cs
  47. 6
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EventDeclaration.cs
  48. 15
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ExtensionDeclaration.cs
  49. 2
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FieldDeclaration.cs
  50. 4
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/IndexerDeclaration.cs
  51. 2
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs
  52. 2
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs
  53. 8
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs
  54. 4
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  55. 2
      ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs
  56. 2
      ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs
  57. 1
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs
  58. 4
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs
  59. 4
      ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs
  60. 2
      ICSharpCode.Decompiler/CSharp/Transforms/PrettifyAssignments.cs
  61. 2
      ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs
  62. 2
      ICSharpCode.Decompiler/IL/ILAmbience.cs
  63. 2
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs
  64. 2
      ILSpy/Languages/CSharpLanguage.cs

59
ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.Decompiler.Generators; @@ -30,7 +30,7 @@ namespace ICSharpCode.Decompiler.Generators;
[Generator]
internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator
{
record AstNodeAdditions(string NodeName, bool NeedsAcceptImpls, bool NeedsVisitor, bool NeedsNullNode, bool NeedsPatternPlaceholder, int NullNodeBaseCtorParamCount, bool IsTypeNode, string VisitMethodName, string VisitMethodParamType, EquatableArray<(string Member, string TypeName, bool RecursiveMatch, bool MatchAny, bool Nullable)>? MembersToMatch, EquatableArray<(string RoleExpr, bool IsCollection, string PropertyName, string PropertyType, string ElementType, bool IsOverride, bool IsNullable, string KindName, bool IsPartial)>? Slots, EquatableArray<(string StringName, string TokenName, bool NullOnEmpty)>? NameSlots);
record AstNodeAdditions(string NodeName, bool NeedsVisitor, bool NeedsNullNode, bool NeedsPatternPlaceholder, int NullNodeBaseCtorParamCount, bool IsTypeNode, string VisitMethodName, string VisitMethodParamType, EquatableArray<(string Member, string TypeName, bool RecursiveMatch, bool MatchAny, bool Nullable)>? MembersToMatch, EquatableArray<(string RoleExpr, bool IsCollection, string PropertyName, string PropertyType, string ElementType, bool IsOverride, bool IsNullable, string KindName, bool IsPartial)>? Slots, EquatableArray<(string StringName, string TokenName, bool NullOnEmpty)>? NameSlots);
// Derives the shared SlotKind name from a [Slot] role expression: the last dotted segment with a
// trailing "Role" removed (e.g. "Roles.EmbeddedStatement" -> "EmbeddedStatement", "LeftRole" ->
@ -80,7 +80,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator @@ -80,7 +80,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator
if (!excludeName)
membersToMatch.Add(("Name", "String", false, false, false));
membersToMatch.Add(("MatchAttributesAndModifiers", null!, false, false, false));
membersToMatch.Add(("ReturnType", "AstType", true, false, false));
membersToMatch.Add(("ReturnType", "AstType", true, false, true));
}
foreach (var m in targetSymbol.GetMembers())
@ -149,7 +149,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator @@ -149,7 +149,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator
}
}
return new(targetSymbol.Name, !targetSymbol.MemberNames.Contains("AcceptVisitor"),
return new(targetSymbol.Name,
NeedsVisitor: !targetSymbol.IsAbstract && targetSymbol.BaseType!.IsAbstract,
NeedsNullNode: (bool)attribute.ConstructorArguments[0].Value!,
NeedsPatternPlaceholder: (bool)attribute.ConstructorArguments[1].Value!,
@ -184,51 +184,6 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator @@ -184,51 +184,6 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator
builder.AppendLine($"partial class {source.NodeName}");
builder.AppendLine("{");
if (source.NeedsNullNode)
{
bool needsNew = source.NodeName != "AstNode";
builder.AppendLine($" {(needsNew ? "new " : "")}public static readonly {source.NodeName} Null = new Null{source.NodeName}();");
builder.AppendLine($@"
sealed class Null{source.NodeName} : {source.NodeName}
{{
public override bool IsNull => true;
public override void AcceptVisitor(IAstVisitor visitor)
{{
visitor.VisitNullNode(this);
}}
public override T AcceptVisitor<T>(IAstVisitor<T> visitor)
{{
return visitor.VisitNullNode(this);
}}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{{
return visitor.VisitNullNode(this, data);
}}
protected internal override bool DoMatch(AstNode? other, PatternMatching.Match match)
{{
return other == null || other.IsNull;
}}");
if (source.NullNodeBaseCtorParamCount > 0)
{
builder.AppendLine($@"
public Null{source.NodeName}() : base({string.Join(", ", Enumerable.Repeat("default", source.NullNodeBaseCtorParamCount))}) {{ }}");
}
builder.AppendLine($@"
}}
");
}
if (source.NeedsPatternPlaceholder)
{
// The placeholder conversion is part of the pattern-construction DSL, where a non-null
@ -283,7 +238,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator @@ -283,7 +238,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator
);
}
if (source.NeedsAcceptImpls && source.NeedsVisitor)
if (source.NeedsVisitor)
{
builder.Append($@" public override void AcceptVisitor(IAstVisitor visitor)
{{
@ -307,7 +262,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator @@ -307,7 +262,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator
{
builder.Append($@" protected internal override bool DoMatch(AstNode? other, PatternMatching.Match match)
{{
return other is {source.NodeName} o && !o.IsNull");
return other is {source.NodeName} o");
foreach (var (member, typeName, recursive, hasAny, nullable) in source.MembersToMatch)
{
@ -366,7 +321,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator @@ -366,7 +321,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator
builder.AppendLine($"\t{type}? {field};");
builder.AppendLine($"\tpublic {(isOverride ? "override " : "")}{partialKw}{type}{(isNullable ? "?" : "")} {name}");
builder.AppendLine("\t{");
builder.AppendLine($"\t\tget => {field}{(isNullable ? "" : $" ?? {roleExpr}.NullObject")};");
builder.AppendLine($"\t\tget => {field}{(isNullable ? "" : "!")};");
builder.AppendLine($"\t\tset => SetChildNode(ref {field}, value, {roleExpr});");
builder.AppendLine("\t}");
}
@ -514,7 +469,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator @@ -514,7 +469,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator
builder.AppendLine("namespace ICSharpCode.Decompiler.CSharp.Syntax;");
source = source
.Concat([new("NullNode", false, true, false, false, 0, false, "NullNode", "AstNode", null, null, null), new("PatternPlaceholder", false, true, false, false, 0, false, "PatternPlaceholder", "AstNode", null, null, null)])
.Concat([new("PatternPlaceholder", true, false, false, 0, false, "PatternPlaceholder", "AstNode", null, null, null)])
.ToImmutableArray();
WriteInterface("IAstVisitor", "void", "");

6
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1406,7 +1406,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1406,7 +1406,7 @@ namespace ICSharpCode.Decompiler.CSharp
EntityDeclaration memberDecl, IMethod method,
TypeSystemAstBuilder astBuilder)
{
if (!memberDecl.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole).IsNull)
if (memberDecl.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole) is not null)
{
yield break; // cannot create forwarder for existing explicit interface impl
}
@ -1427,7 +1427,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1427,7 +1427,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (m == null || m.DeclaringType.Kind != TypeKind.Interface)
continue;
var methodDecl = new MethodDeclaration();
methodDecl.ReturnType = memberDecl.ReturnType.Clone();
methodDecl.ReturnType = memberDecl.ReturnType?.Clone();
methodDecl.PrivateImplementationType = astBuilder.ConvertType(m.DeclaringType);
methodDecl.Name = m.Name;
methodDecl.TypeParameters.AddRange(memberDecl.GetChildrenByRole(Roles.TypeParameter)
@ -2041,7 +2041,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2041,7 +2041,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
var methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
var body = BlockStatement.Null;
BlockStatement body = new BlockStatement();
MethodBodyBlock methodBody;
try
{

6
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -2182,19 +2182,19 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2182,19 +2182,19 @@ namespace ICSharpCode.Decompiler.CSharp
}
else if (callOpCode == OpCode.Call && method.Name == "get_All" && argumentList.Length == 0)
{
result = new BinaryOperatorExpression(Expression.Null, BinaryOperatorType.Range, Expression.Null)
result = new BinaryOperatorExpression(null, BinaryOperatorType.Range, null)
.WithRR(new MemberResolveResult(null, method.AccessorOwner ?? method));
return true;
}
else if (callOpCode == OpCode.Call && method.Name == "StartAt" && argumentList.Length == 1)
{
result = new BinaryOperatorExpression(argumentList.Arguments[0], BinaryOperatorType.Range, Expression.Null)
result = new BinaryOperatorExpression(argumentList.Arguments[0], BinaryOperatorType.Range, null)
.WithRR(new MemberResolveResult(null, method));
return true;
}
else if (callOpCode == OpCode.Call && method.Name == "EndAt" && argumentList.Length == 1)
{
result = new BinaryOperatorExpression(Expression.Null, BinaryOperatorType.Range, argumentList.Arguments[0])
result = new BinaryOperatorExpression(null, BinaryOperatorType.Range, argumentList.Arguments[0])
.WithRR(new MemberResolveResult(null, method));
return true;
}

4
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs

@ -124,7 +124,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -124,7 +124,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
&& (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType)
{
var rt = node.GetChildByRole(Roles.Type);
if (!rt.IsNull)
if (rt is not null)
{
rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
writer.Space();
@ -182,7 +182,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -182,7 +182,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
&& (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType)
{
var rt = node.GetChildByRole(Roles.Type);
if (!rt.IsNull)
if (rt is not null)
{
writer.Space();
writer.WriteToken(Roles.Colon, ":");

46
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -502,7 +502,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -502,7 +502,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
/// </remarks>
protected virtual void WriteEmbeddedStatement(Statement embeddedStatement, NewLinePlacement nlp = NewLinePlacement.NewLine)
{
if (embeddedStatement.IsNull)
if (embeddedStatement is null)
{
NewLine();
return;
@ -531,7 +531,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -531,7 +531,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
protected virtual void WriteMethodBody(BlockStatement body, BraceStyle style, bool newLine = true)
{
if (body is null || body.IsNull)
if (body is null)
{
Semicolon();
}
@ -552,7 +552,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -552,7 +552,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
protected virtual void WritePrivateImplementationType(AstType privateImplementationType)
{
if (privateImplementationType is not null && !privateImplementationType.IsNull)
if (privateImplementationType is not null)
{
privateImplementationType.AcceptVisitor(this);
WriteToken(Roles.Dot);
@ -611,7 +611,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -611,7 +611,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(arrayCreateExpression);
WriteKeyword(ArrayCreateExpression.NewKeywordRole);
arrayCreateExpression.Type.AcceptVisitor(this);
arrayCreateExpression.Type?.AcceptVisitor(this);
if (arrayCreateExpression.Arguments.Count > 0)
{
WriteCommaSeparatedListInBrackets(arrayCreateExpression.Arguments);
@ -765,7 +765,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -765,7 +765,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
public virtual void VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression)
{
StartNode(binaryOperatorExpression);
binaryOperatorExpression.Left.AcceptVisitor(this);
binaryOperatorExpression.Left?.AcceptVisitor(this);
bool spacePolicy;
switch (binaryOperatorExpression.Operator)
{
@ -823,7 +823,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -823,7 +823,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
WriteToken(tokenRole);
}
Space(spacePolicy);
binaryOperatorExpression.Right.AcceptVisitor(this);
binaryOperatorExpression.Right?.AcceptVisitor(this);
EndNode(binaryOperatorExpression);
}
@ -1361,7 +1361,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1361,7 +1361,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
StartNode(queryFromClause);
WriteKeyword(QueryFromClause.FromKeywordRole);
Space();
queryFromClause.Type.AcceptVisitor(this);
queryFromClause.Type?.AcceptVisitor(this);
Space();
WriteIdentifier(queryFromClause.IdentifierToken);
Space();
@ -1397,7 +1397,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1397,7 +1397,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(queryJoinClause);
WriteKeyword(QueryJoinClause.JoinKeywordRole);
queryJoinClause.Type.AcceptVisitor(this);
queryJoinClause.Type?.AcceptVisitor(this);
Space();
WriteIdentifier(queryJoinClause.JoinIdentifierToken);
Space();
@ -1523,7 +1523,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1523,7 +1523,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
WriteAttributes(delegateDeclaration.Attributes);
WriteModifiers(delegateDeclaration.Modifiers);
WriteKeyword(Roles.DelegateKeyword);
delegateDeclaration.ReturnType.AcceptVisitor(this);
delegateDeclaration.ReturnType?.AcceptVisitor(this);
Space();
WriteIdentifier(delegateDeclaration.NameToken);
WriteTypeParameters(delegateDeclaration.TypeParameters);
@ -2416,7 +2416,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2416,7 +2416,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
WriteAttributes(eventDeclaration.Attributes);
WriteModifiers(eventDeclaration.Modifiers);
WriteKeyword(EventDeclaration.EventKeywordRole);
eventDeclaration.ReturnType.AcceptVisitor(this);
eventDeclaration.ReturnType?.AcceptVisitor(this);
Space();
WriteCommaSeparatedList(eventDeclaration.Variables);
Semicolon();
@ -2429,7 +2429,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2429,7 +2429,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
WriteAttributes(customEventDeclaration.Attributes);
WriteModifiers(customEventDeclaration.Modifiers);
WriteKeyword(CustomEventDeclaration.EventKeywordRole);
customEventDeclaration.ReturnType.AcceptVisitor(this);
customEventDeclaration.ReturnType?.AcceptVisitor(this);
Space();
WritePrivateImplementationType(customEventDeclaration.PrivateImplementationType);
WriteIdentifier(customEventDeclaration.NameToken);
@ -2452,7 +2452,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2452,7 +2452,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
StartNode(fieldDeclaration);
WriteAttributes(fieldDeclaration.Attributes);
WriteModifiers(fieldDeclaration.Modifiers);
fieldDeclaration.ReturnType.AcceptVisitor(this);
fieldDeclaration.ReturnType?.AcceptVisitor(this);
Space();
WriteCommaSeparatedList(fieldDeclaration.Variables);
Semicolon();
@ -2466,7 +2466,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2466,7 +2466,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
WriteModifiers(fixedFieldDeclaration.Modifiers);
WriteKeyword(FixedFieldDeclaration.FixedKeywordRole);
Space();
fixedFieldDeclaration.ReturnType.AcceptVisitor(this);
fixedFieldDeclaration.ReturnType?.AcceptVisitor(this);
Space();
WriteCommaSeparatedList(fixedFieldDeclaration.Variables);
Semicolon();
@ -2477,7 +2477,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2477,7 +2477,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(fixedVariableInitializer);
WriteIdentifier(fixedVariableInitializer.NameToken);
if (!fixedVariableInitializer.CountExpression.IsNull)
if (fixedVariableInitializer.CountExpression is not null)
{
WriteToken(Roles.LBracket);
Space(policy.SpacesWithinBrackets);
@ -2493,7 +2493,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2493,7 +2493,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
StartNode(indexerDeclaration);
WriteAttributes(indexerDeclaration.Attributes);
WriteModifiers(indexerDeclaration.Modifiers);
indexerDeclaration.ReturnType.AcceptVisitor(this);
indexerDeclaration.ReturnType?.AcceptVisitor(this);
Space();
WritePrivateImplementationType(indexerDeclaration.PrivateImplementationType);
WriteKeyword(IndexerDeclaration.ThisKeywordRole);
@ -2538,7 +2538,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2538,7 +2538,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
StartNode(methodDeclaration);
WriteAttributes(methodDeclaration.Attributes);
WriteModifiers(methodDeclaration.Modifiers);
methodDeclaration.ReturnType.AcceptVisitor(this);
methodDeclaration.ReturnType?.AcceptVisitor(this);
Space();
WritePrivateImplementationType(methodDeclaration.PrivateImplementationType);
WriteIdentifier(methodDeclaration.NameToken);
@ -2568,7 +2568,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2568,7 +2568,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
else
{
operatorDeclaration.ReturnType.AcceptVisitor(this);
operatorDeclaration.ReturnType?.AcceptVisitor(this);
}
Space();
WritePrivateImplementationType(operatorDeclaration.PrivateImplementationType);
@ -2583,7 +2583,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2583,7 +2583,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
|| operatorDeclaration.OperatorType == OperatorType.CheckedExplicit
|| operatorDeclaration.OperatorType == OperatorType.Implicit)
{
operatorDeclaration.ReturnType.AcceptVisitor(this);
operatorDeclaration.ReturnType?.AcceptVisitor(this);
}
else
{
@ -2658,7 +2658,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2658,7 +2658,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
StartNode(propertyDeclaration);
WriteAttributes(propertyDeclaration.Attributes);
WriteModifiers(propertyDeclaration.Modifiers);
propertyDeclaration.ReturnType.AcceptVisitor(this);
propertyDeclaration.ReturnType?.AcceptVisitor(this);
Space();
WritePrivateImplementationType(propertyDeclaration.PrivateImplementationType);
WriteIdentifier(propertyDeclaration.NameToken);
@ -2682,7 +2682,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2682,7 +2682,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
}
CloseBrace(isSingleLine ? BraceStyle.EndOfLine : policy.PropertyBraceStyle, unindent: !isSingleLine);
if (!propertyDeclaration.Initializer.IsNull)
if (propertyDeclaration.Initializer is not null)
{
Space(policy.SpaceAroundAssignment);
WriteToken(Roles.Assign);
@ -2752,6 +2752,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2752,6 +2752,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
public virtual void VisitSimpleType(SimpleType simpleType)
{
StartNode(simpleType);
// An unbound generic type argument (the '' in 'typeof(List<>)') is a nameless SimpleType.
if (simpleType.IdentifierToken is not null)
WriteIdentifier(simpleType.IdentifierToken);
WriteTypeArguments(simpleType.TypeArguments);
EndNode(simpleType);
@ -2956,10 +2958,6 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2956,10 +2958,6 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
WriteIdentifier(identifier);
}
void IAstVisitor.VisitNullNode(AstNode nullNode)
{
}
void IAstVisitor.VisitErrorNode(AstNode errorNode)
{
StartNode(errorNode);

2
ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs

@ -142,7 +142,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -142,7 +142,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
public override void WriteIdentifier(Identifier identifier)
{
AssignPendingStartLocations();
if (!identifier.IsNull)
if (identifier is not null)
identifier.SetStartLocation(locationProvider.Location);
currentList.Add(identifier);
base.WriteIdentifier(identifier);

2
ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs

@ -96,7 +96,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -96,7 +96,7 @@ namespace ICSharpCode.Decompiler.CSharp
void VisitAsSequencePoint(AstNode node)
{
if (node is null || node.IsNull)
if (node is null)
return;
StartSequencePoint(node);
node.AcceptVisitor(this);

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

@ -57,12 +57,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -57,12 +57,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
const uint roleIndexMask = (1u << Role.RoleIndexBits) - 1;
protected const int AstNodeFlagsUsedBits = Role.RoleIndexBits;
public virtual bool IsNull {
get {
return false;
}
}
TextLocation startLocation = TextLocation.Empty;
TextLocation endLocation = TextLocation.Empty;
@ -480,7 +474,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -480,7 +474,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
// A null or null-object value empties the slot. Called by generated single-slot property setters.
internal void SetChildNode<T>(ref T? field, T? value, Role role) where T : AstNode
{
T? newValue = (value == null || value.IsNull) ? null : value;
T? newValue = value;
if (field == newValue)
return;
if (newValue != null)
@ -520,14 +514,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -520,14 +514,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
if (role == null)
throw new ArgumentNullException(nameof(role));
if (child == null || child.IsNull)
if (child == null)
return;
AddChildUnsafe(child, role);
}
public void AddChildWithExistingRole(AstNode? child)
{
if (child == null || child.IsNull)
if (child == null)
return;
AddChildUnsafe(child, child.Role);
}
@ -555,7 +549,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -555,7 +549,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
if (GetChildSlot(i) == role)
{
SetChild(i, child == null || child.IsNull ? null : child);
SetChild(i, child);
return;
}
}
@ -566,11 +560,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -566,11 +560,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
if (role == null)
throw new ArgumentNullException(nameof(role));
if (child == null || child.IsNull)
if (child == null)
return;
AstNodeCollection? collection = GetCollectionByRole(role);
if (collection != null)
collection.InsertNodeBefore((nextSibling == null || nextSibling.IsNull) ? null : nextSibling, child);
collection.InsertNodeBefore(nextSibling, child);
else
SetChildByRoleUntyped(role, child);
}
@ -588,11 +582,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -588,11 +582,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
if (role == null)
throw new ArgumentNullException(nameof(role));
if (child == null || child.IsNull)
if (child == null)
return;
AstNodeCollection? collection = GetCollectionByRole(role);
if (collection != null)
collection.InsertNodeAfter((prevSibling == null || prevSibling.IsNull) ? null : prevSibling, child);
collection.InsertNodeAfter(prevSibling, child);
else
SetChildByRoleUntyped(role, child);
}
@ -618,7 +612,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -618,7 +612,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// </summary>
public void ReplaceWith(AstNode? newNode)
{
if (newNode == null || newNode.IsNull)
if (newNode == null)
{
Remove();
return;
@ -627,7 +621,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -627,7 +621,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return; // nothing to do...
if (parent == null)
{
throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node");
throw new InvalidOperationException("Cannot replace the root node");
}
parent.EnsureChildIndices();
Role role = parent.GetChildSlot(childIndex);
@ -660,7 +654,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -660,7 +654,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
throw new ArgumentNullException(nameof(replaceFunction));
if (parent == null)
{
throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node");
throw new InvalidOperationException("Cannot replace the root node");
}
AstNode oldParent = parent;
AstNode? oldSuccessor = NextSibling;
@ -669,7 +663,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -669,7 +663,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
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))
if (replacement != null)
{
if (replacement.parent != null)
throw new InvalidOperationException("replace function must return the root of a tree");
@ -839,8 +833,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -839,8 +833,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// </param>
public virtual string ToString(CSharpFormattingOptions? formattingOptions)
{
if (IsNull)
return "";
var w = new StringWriter();
AcceptVisitor(new CSharpOutputVisitor(w, formattingOptions ?? FormattingOptionsFactory.CreateMono()));
return w.ToString();
@ -897,15 +889,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -897,15 +889,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public override void AddAnnotation(object annotation)
{
if (this.IsNull)
throw new InvalidOperationException("Cannot add annotations to the null node");
base.AddAnnotation(annotation);
}
internal string DebugToString()
{
if (IsNull)
return "Null";
string text = ToString();
text = text.TrimEnd().Replace("\t", "").Replace(Environment.NewLine, " ");
if (text.Length > 100)

4
ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs

@ -114,7 +114,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -114,7 +114,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public void Add(T element)
{
if (element == null || element.IsNull)
if (element == null)
return;
ValidateNewChild(element);
list.Add(element);
@ -318,7 +318,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -318,7 +318,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
void Insert(int index, T newItem)
{
if (newItem == null || newItem.IsNull)
if (newItem == null)
return;
ValidateNewChild(newItem);
list.Insert(index, newItem);

26
ICSharpCode.Decompiler/CSharp/Syntax/DepthFirstAstVisitor.cs

@ -43,14 +43,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -43,14 +43,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
public virtual void VisitNullNode(AstNode nullNode)
{
// Should we call VisitChildren here?
// We usually want to ignore null nodes.
// Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes;
// so changing this might break VisitChildren() overrides that expect the node to be part of the AST.
}
public virtual void VisitSyntaxTree(SyntaxTree syntaxTree)
{
VisitChildren(syntaxTree);
@ -726,15 +718,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -726,15 +718,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return default(T);
}
public virtual T VisitNullNode(AstNode nullNode)
{
// Should we call VisitChildren here?
// We usually want to ignore null nodes.
// Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes;
// so changing this might break VisitChildren() overrides that expect the node to be part of the AST.
return default(T);
}
public virtual T VisitSyntaxTree(SyntaxTree unit)
{
return VisitChildren(unit);
@ -1410,15 +1393,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1410,15 +1393,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return default(S);
}
public virtual S VisitNullNode(AstNode nullNode, T data)
{
// Should we call VisitChildren here?
// We usually want to ignore null nodes.
// Older NR versions (before VisitNullNode was introduced) didn't call VisitChildren() with null nodes;
// so changing this might break VisitChildren() overrides that expect the node to be part of the AST.
return default(S);
}
public virtual S VisitSyntaxTree(SyntaxTree unit, T data)
{
return VisitChildren(unit, data);

4
ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs

@ -34,8 +34,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -34,8 +34,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: false)]
public partial class DocumentationReference : AstNode
{
public static readonly Role<AstType> DeclaringTypeRole = new Role<AstType>("DeclaringType", AstType.Null);
public static readonly Role<AstType> ConversionOperatorReturnTypeRole = new Role<AstType>("ConversionOperatorReturnType", AstType.Null);
public static readonly Role<AstType> DeclaringTypeRole = new Role<AstType>("DeclaringType", null);
public static readonly Role<AstType> ConversionOperatorReturnTypeRole = new Role<AstType>("ConversionOperatorReturnType", null);
SymbolKind symbolKind;
OperatorType operatorType;

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

@ -28,10 +28,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -28,10 +28,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public readonly static TokenRole NewKeywordRole = new TokenRole("new");
public readonly static Role<ArraySpecifier> AdditionalArraySpecifierRole = new Role<ArraySpecifier>("AdditionalArraySpecifier", null);
public readonly static Role<ArrayInitializerExpression> InitializerRole = new Role<ArrayInitializerExpression>("Initializer", ArrayInitializerExpression.Null);
public readonly static Role<ArrayInitializerExpression> InitializerRole = new Role<ArrayInitializerExpression>("Initializer", null);
[Slot("Roles.Type")]
public partial AstType Type { get; set; }
public partial AstType? Type { get; set; }
[Slot("Roles.Argument")]
public partial AstNodeCollection<Expression> Arguments { get; }

12
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs

@ -27,6 +27,8 @@ @@ -27,6 +27,8 @@
using System;
using System.Linq.Expressions;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
/// <summary>
@ -60,14 +62,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -60,14 +62,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public readonly static TokenRole RangeRole = new TokenRole("..");
public readonly static TokenRole IsKeywordRole = IsExpression.IsKeywordRole;
public readonly static Role<Expression> LeftRole = new Role<Expression>("Left", Expression.Null);
public readonly static Role<Expression> RightRole = new Role<Expression>("Right", Expression.Null);
public readonly static Role<Expression> LeftRole = new Role<Expression>("Left", null);
public readonly static Role<Expression> RightRole = new Role<Expression>("Right", null);
public BinaryOperatorExpression()
{
}
public BinaryOperatorExpression(Expression left, BinaryOperatorType op, Expression right)
public BinaryOperatorExpression(Expression? left, BinaryOperatorType op, Expression? right)
{
this.Left = left;
this.Operator = op;
@ -80,10 +82,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -80,10 +82,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
[Slot(nameof(LeftRole))]
public partial Expression Left { get; set; }
public partial Expression? Left { get; set; }
[Slot(nameof(RightRole))]
public partial Expression Right { get; set; }
public partial Expression? Right { get; set; }
public static TokenRole GetOperatorRole(BinaryOperatorType op)
{

4
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ConditionalExpression.cs

@ -34,9 +34,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -34,9 +34,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public readonly static Role<Expression> ConditionRole = Roles.Condition;
public readonly static TokenRole QuestionMarkRole = new TokenRole("?");
public readonly static Role<Expression> TrueRole = new Role<Expression>("True", Expression.Null);
public readonly static Role<Expression> TrueRole = new Role<Expression>("True", null);
public readonly static TokenRole ColonRole = Roles.Colon;
public readonly static Role<Expression> FalseRole = new Role<Expression>("False", Expression.Null);
public readonly static Role<Expression> FalseRole = new Role<Expression>("False", null);
[Slot("ConditionRole")]
public partial Expression Condition { get; set; }

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

@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: true)]
public abstract partial class InterpolatedStringContent : AstNode
{
public new static readonly Role<InterpolatedStringContent> Role = new Role<InterpolatedStringContent>("InterpolatedStringContent", Syntax.InterpolatedStringContent.Null);
public new static readonly Role<InterpolatedStringContent> Role = new Role<InterpolatedStringContent>("InterpolatedStringContent", null);
}

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

@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public static readonly Role<AttributeSection> AttributeRole = new Role<AttributeSection>("Attribute", null);
public readonly static TokenRole AsyncModifierRole = new TokenRole("async");
public static readonly Role<AstNode> BodyRole = new Role<AstNode>("Body", AstNode.Null);
public static readonly Role<AstNode> BodyRole = new Role<AstNode>("Body", null);
bool isAsync;

20
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.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
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
/// <summary>
@ -43,7 +45,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -43,7 +45,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: false)]
public partial class QueryContinuationClause : QueryClause
{
public static readonly Role<QueryExpression> PrecedingQueryRole = new Role<QueryExpression>("PrecedingQuery", QueryExpression.Null);
public static readonly Role<QueryExpression> PrecedingQueryRole = new Role<QueryExpression>("PrecedingQuery", null);
public static readonly TokenRole IntoKeywordRole = new TokenRole("into");
[Slot("PrecedingQueryRole")]
@ -63,7 +65,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -63,7 +65,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly TokenRole InKeywordRole = new TokenRole("in");
[Slot("Roles.Type")]
public partial AstType Type { get; set; }
public partial AstType? Type { get; set; }
[NameSlot("Roles.Identifier")]
public partial string Identifier { get; set; }
@ -118,11 +120,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -118,11 +120,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly TokenRole InKeywordRole = new TokenRole("in");
public static readonly Role<Expression> InExpressionRole = Roles.Expression;
public static readonly TokenRole OnKeywordRole = new TokenRole("on");
public static readonly Role<Expression> OnExpressionRole = new Role<Expression>("OnExpression", Expression.Null);
public static readonly Role<Expression> OnExpressionRole = new Role<Expression>("OnExpression", null);
public static readonly TokenRole EqualsKeywordRole = new TokenRole("equals");
public static readonly Role<Expression> EqualsExpressionRole = new Role<Expression>("EqualsExpression", Expression.Null);
public static readonly Role<Expression> EqualsExpressionRole = new Role<Expression>("EqualsExpression", null);
public static readonly TokenRole IntoKeywordRole = new TokenRole("into");
public static readonly Role<Identifier> IntoIdentifierRole = new Role<Identifier>("IntoIdentifier", Identifier.Null);
public static readonly Role<Identifier> IntoIdentifierRole = new Role<Identifier>("IntoIdentifier", null);
// Derived from IntoIdentifier (which DoMatch already compares); exclude it to avoid a redundant compare.
[ExcludeFromMatch]
@ -131,7 +133,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -131,7 +133,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
[Slot("TypeRole")]
public partial AstType Type { get; set; }
public partial AstType? Type { get; set; }
[NameSlot("JoinIdentifierRole")]
public partial string JoinIdentifier { get; set; }
@ -145,7 +147,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -145,7 +147,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[Slot("EqualsExpressionRole")]
public partial Expression EqualsExpression { get; set; }
[NameSlot("IntoIdentifierRole")]
[NameSlot("IntoIdentifierRole", nullOnEmpty: true)]
public partial string IntoIdentifier { get; set; }
}
@ -206,9 +208,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -206,9 +208,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public partial class QueryGroupClause : QueryClause
{
public static readonly TokenRole GroupKeywordRole = new TokenRole("group");
public static readonly Role<Expression> ProjectionRole = new Role<Expression>("Projection", Expression.Null);
public static readonly Role<Expression> ProjectionRole = new Role<Expression>("Projection", null);
public static readonly TokenRole ByKeywordRole = new TokenRole("by");
public static readonly Role<Expression> KeyRole = new Role<Expression>("Key", Expression.Null);
public static readonly Role<Expression> KeyRole = new Role<Expression>("Key", null);
[Slot("ProjectionRole")]
public partial Expression Projection { get; set; }

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

@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: false)]
public partial class RecursivePatternExpression : Expression
{
public static readonly Role<Expression> SubPatternRole = new Role<Expression>("SubPattern", Syntax.Expression.Null);
public static readonly Role<Expression> SubPatternRole = new Role<Expression>("SubPattern", null);
[Slot("Roles.Type")]
public partial AstType? Type { get; set; }

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

@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public partial class StackAllocExpression : Expression
{
public readonly static TokenRole StackallocKeywordRole = new TokenRole("stackalloc");
public readonly static Role<ArrayInitializerExpression> InitializerRole = new Role<ArrayInitializerExpression>("Initializer", ArrayInitializerExpression.Null);
public readonly static Role<ArrayInitializerExpression> InitializerRole = new Role<ArrayInitializerExpression>("Initializer", null);
[Slot("Roles.Type")]
public partial AstType? Type { get; set; }

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

@ -41,8 +41,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -41,8 +41,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: false)]
public partial class SwitchExpressionSection : AstNode
{
public static readonly Role<Expression> PatternRole = new Role<Expression>("Pattern", Expression.Null);
public static readonly Role<Expression> BodyRole = new Role<Expression>("Body", Expression.Null);
public static readonly Role<Expression> PatternRole = new Role<Expression>("Pattern", null);
public static readonly Role<Expression> BodyRole = new Role<Expression>("Body", null);
[Slot("PatternRole")]
public partial Expression Pattern { get; set; }

2
ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerAstType.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public partial class FunctionPointerAstType : AstType
{
public static readonly TokenRole PointerRole = new TokenRole("*");
public static readonly Role<AstType> CallingConventionRole = new Role<AstType>("CallConv", AstType.Null);
public static readonly Role<AstType> CallingConventionRole = new Role<AstType>("CallConv", null);
public bool HasUnmanagedCallingConvention { get; set; }

2
ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Attribute.cs

@ -49,8 +49,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -49,8 +49,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public override string ToString(CSharpFormattingOptions formattingOptions)
{
if (IsNull)
return "Null";
return base.ToString(formattingOptions);
}
}

2
ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/AttributeSection.cs

@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public string AttributeTarget {
get {
return GetChildByRole(Roles.Identifier).Name;
return GetChildByRole(Roles.Identifier)?.Name ?? string.Empty;
}
set {
SetChildByRole(Roles.Identifier, Identifier.Create(value));

2
ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/NamespaceDeclaration.cs

@ -40,7 +40,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -40,7 +40,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public partial class NamespaceDeclaration : AstNode
{
public static readonly Role<AstNode> MemberRole = SyntaxTree.MemberRole;
public static readonly Role<AstType> NamespaceNameRole = new Role<AstType>("NamespaceName", AstType.Null);
public static readonly Role<AstType> NamespaceNameRole = new Role<AstType>("NamespaceName", null);
public bool IsFileScoped { get; set; }

2
ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingAliasDeclaration.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public partial class UsingAliasDeclaration : AstNode
{
public static readonly TokenRole UsingKeywordRole = new TokenRole("using");
public static readonly Role<Identifier> AliasRole = new Role<Identifier>("Alias", Identifier.Null);
public static readonly Role<Identifier> AliasRole = new Role<Identifier>("Alias", null);
public static readonly Role<AstType> ImportRole = UsingDeclaration.ImportRole;
[NameSlot("AliasRole")]

2
ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingDeclaration.cs

@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public partial class UsingDeclaration : AstNode
{
public static readonly TokenRole UsingKeywordRole = new TokenRole("using");
public static readonly Role<AstType> ImportRole = new Role<AstType>("Import", AstType.Null);
public static readonly Role<AstType> ImportRole = new Role<AstType>("Import", null);
[Slot("ImportRole")]
public partial AstType Import { get; set; }

4
ICSharpCode.Decompiler/CSharp/Syntax/Identifier.cs

@ -106,7 +106,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -106,7 +106,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static Identifier Create(string name, TextLocation location)
{
if (string.IsNullOrEmpty(name))
return Identifier.Null;
return new Identifier(string.Empty, location);
if (name[0] == '@')
return new Identifier(name.Substring(1), new TextLocation(location.Line, location.Column + 1)) { IsVerbatim = true };
else
@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static Identifier Create(string name, TextLocation location, bool isVerbatim)
{
if (string.IsNullOrEmpty(name))
return Identifier.Null;
return new Identifier(string.Empty, location);
if (isVerbatim)
return new Identifier(name, location) { IsVerbatim = true };

2
ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: false)]
public partial class MemberType : AstType
{
public static readonly Role<AstType> TargetRole = new Role<AstType>("Target", AstType.Null);
public static readonly Role<AstType> TargetRole = new Role<AstType>("Target", null);
bool isDoubleColon;

2
ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/AnyNode.cs

@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching @@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching
public override bool DoMatch(INode other, Match match)
{
match.Add(this.groupName, other);
return other != null && !other.IsNull;
return other != null;
}
}

2
ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/INode.cs

@ -26,8 +26,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching @@ -26,8 +26,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching
/// </summary>
public interface INode
{
bool IsNull { get; }
bool DoMatch(INode other, Match match);
/// <summary>

2
ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/OptionalNode.cs

@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching
public override bool DoMatch(INode other, Match match)
{
if (other == null || other.IsNull)
if (other == null)
return true;
else
return childNode.DoMatch(other, match);

4
ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Pattern.cs

@ -48,10 +48,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching @@ -48,10 +48,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching
}
}
bool INode.IsNull {
get { return false; }
}
public abstract bool DoMatch(INode other, Match match);
public virtual bool DoMatchCollection(IReadOnlyList<INode> other, int pos, Match match, BacktrackingInfo backtrackingInfo)

2
ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/Repeat.cs

@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching @@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching
public override bool DoMatch(INode other, Match match)
{
if (other == null || other.IsNull)
if (other == null)
return this.MinCount <= 0;
else
return this.MaxCount >= 1 && childNode.DoMatch(other, match);

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

@ -31,22 +31,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -31,22 +31,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly Role<AstNode> Root = AstNode.RootRole;
// 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<Identifier> Identifier = new Role<Identifier>("Identifier", null);
public static readonly Role<BlockStatement> Body = new Role<BlockStatement>("Body", null);
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<Expression> Argument = new Role<Expression>("Argument", null);
public static readonly Role<AstType> Type = new Role<AstType>("Type", null);
public static readonly Role<Expression> Expression = new Role<Expression>("Expression", null);
public static readonly Role<Expression> TargetExpression = new Role<Expression>("Target", null);
public readonly static Role<Expression> Condition = new Role<Expression>("Condition", null);
public static readonly Role<TypeParameterDeclaration> TypeParameter = new Role<TypeParameterDeclaration>("TypeParameter", null);
public static readonly Role<AstType> TypeArgument = new Role<AstType>("TypeArgument", AstType.Null);
public static readonly Role<AstType> TypeArgument = new Role<AstType>("TypeArgument", null);
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 static readonly Role<VariableInitializer> Variable = new Role<VariableInitializer>("Variable", null);
public static readonly Role<Statement> EmbeddedStatement = new Role<Statement>("EmbeddedStatement", null);
public readonly static Role<EntityDeclaration> TypeMemberRole = new Role<EntityDeclaration>("TypeMember", null);
public static readonly Role<VariableDesignation> VariableDesignationRole = new Role<VariableDesignation>("VariableDesignation", VariableDesignation.Null);
public static readonly Role<VariableDesignation> VariableDesignationRole = new Role<VariableDesignation>("VariableDesignation", null);
// some pre defined constants for most used punctuation
public static readonly TokenRole LPar = new TokenRole("(");
@ -67,12 +67,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -67,12 +67,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
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 readonly static Role<AstType> BaseType = new Role<AstType>("BaseType", null);
public static readonly Role<Attribute> Attribute = new Role<Attribute>("Attribute", null);
public readonly static TokenRole WhereKeyword = new TokenRole("where");
public readonly static Role<SimpleType> ConstraintTypeParameter = new Role<SimpleType>("TypeParameter", SimpleType.Null);
public readonly static Role<SimpleType> ConstraintTypeParameter = new Role<SimpleType>("TypeParameter", null);
public readonly static TokenRole DelegateKeyword = new TokenRole("delegate");
public static readonly TokenRole ExternKeyword = new TokenRole("extern");
public static readonly TokenRole AliasKeyword = new TokenRole("alias");

2
ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs

@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
}
[NameSlot("Roles.Identifier")]
[NameSlot("Roles.Identifier", nullOnEmpty: true)]
public partial string Identifier { get; set; }
[Slot("Roles.TypeArgument")]

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

@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: true, hasPatternPlaceholder: true)]
public partial class BlockStatement : Statement, IEnumerable<Statement>
{
public static readonly Role<Statement> StatementRole = new Role<Statement>("Statement", Statement.Null);
public static readonly Role<Statement> StatementRole = new Role<Statement>("Statement", null);
[Slot("StatementRole")]
public partial AstNodeCollection<Statement> Statements { get; }

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

@ -35,8 +35,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -35,8 +35,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public partial class ForStatement : Statement
{
public static readonly TokenRole ForKeywordRole = new TokenRole("for");
public readonly static Role<Statement> InitializerRole = new Role<Statement>("Initializer", Statement.Null);
public readonly static Role<Statement> IteratorRole = new Role<Statement>("Iterator", Statement.Null);
public readonly static Role<Statement> InitializerRole = new Role<Statement>("Initializer", null);
public readonly static Role<Statement> IteratorRole = new Role<Statement>("Iterator", null);
/// <summary>
/// Gets the list of initializer statements.

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

@ -36,9 +36,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -36,9 +36,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public readonly static TokenRole IfKeywordRole = new TokenRole("if");
public readonly static Role<Expression> ConditionRole = Roles.Condition;
public readonly static Role<Statement> TrueRole = new Role<Statement>("True", Statement.Null);
public readonly static Role<Statement> TrueRole = new Role<Statement>("True", null);
public readonly static TokenRole ElseKeywordRole = new TokenRole("else");
public readonly static Role<Statement> FalseRole = new Role<Statement>("False", Statement.Null);
public readonly static Role<Statement> FalseRole = new Role<Statement>("False", null);
[Slot("ConditionRole")]
public partial Expression Condition { get; set; }

6
ICSharpCode.Decompiler/CSharp/Syntax/Statements/TryCatchStatement.cs

@ -35,10 +35,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -35,10 +35,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public partial class TryCatchStatement : Statement
{
public static readonly TokenRole TryKeywordRole = new TokenRole("try");
public static readonly Role<BlockStatement> TryBlockRole = new Role<BlockStatement>("TryBlock", BlockStatement.Null);
public static readonly Role<CatchClause> CatchClauseRole = new Role<CatchClause>("CatchClause", CatchClause.Null);
public static readonly Role<BlockStatement> TryBlockRole = new Role<BlockStatement>("TryBlock", null);
public static readonly Role<CatchClause> CatchClauseRole = new Role<CatchClause>("CatchClause", null);
public static readonly TokenRole FinallyKeywordRole = new TokenRole("finally");
public static readonly Role<BlockStatement> FinallyBlockRole = new Role<BlockStatement>("FinallyBlock", BlockStatement.Null);
public static readonly Role<BlockStatement> FinallyBlockRole = new Role<BlockStatement>("FinallyBlock", null);
[Slot("TryBlockRole")]
public partial BlockStatement TryBlock { get; set; }

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

@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public static readonly TokenRole UsingKeywordRole = new TokenRole("using");
public static readonly TokenRole AwaitRole = UnaryOperatorExpression.AwaitRole;
public static readonly Role<AstNode> ResourceAcquisitionRole = new Role<AstNode>("ResourceAcquisition", AstNode.Null);
public static readonly Role<AstNode> ResourceAcquisitionRole = new Role<AstNode>("ResourceAcquisition", null);
public bool IsAsync { get; set; }

2
ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: false)]
public partial class SyntaxTree : AstNode
{
public static readonly Role<AstNode> MemberRole = new Role<AstNode>("Member", AstNode.Null);
public static readonly Role<AstNode> MemberRole = new Role<AstNode>("Member", null);
[Slot("MemberRole")]
public partial AstNodeCollection<AstNode> Members { get; }

2
ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs

@ -24,7 +24,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -24,7 +24,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: false)]
public partial class TupleAstType : AstType
{
public static readonly Role<TupleTypeElement> ElementRole = new Role<TupleTypeElement>("Element", TupleTypeElement.Null);
public static readonly Role<TupleTypeElement> ElementRole = new Role<TupleTypeElement>("Element", null);
[Slot("ElementRole")]
public partial AstNodeCollection<TupleTypeElement> Elements { get; }

2
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/Accessor.cs

@ -63,7 +63,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -63,7 +63,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
public override Identifier NameToken {
get { return Identifier.Null; }
get { return null!; }
set { }
}

2
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ConstructorDeclaration.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: false)]
public partial class ConstructorDeclaration : EntityDeclaration
{
public static readonly Role<ConstructorInitializer> InitializerRole = new Role<ConstructorInitializer>("Initializer", ConstructorInitializer.Null);
public static readonly Role<ConstructorInitializer> InitializerRole = new Role<ConstructorInitializer>("Initializer", null);
public override SymbolKind SymbolKind {
get { return SymbolKind.Constructor; }

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

@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
// Identity marker for modifier keywords in the output (modifiers are scalars, not child nodes);
// the token writer uses it to make the 'override' modifier a go-to-definition reference.
public static readonly TokenRole ModifierRole = new TokenRole("modifier");
public static readonly Role<AstType> PrivateImplementationTypeRole = new Role<AstType>("PrivateImplementationType", AstType.Null);
public static readonly Role<AstType> PrivateImplementationTypeRole = new Role<AstType>("PrivateImplementationType", null);
public abstract SymbolKind SymbolKind { get; }
@ -48,7 +48,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -48,7 +48,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public virtual string Name {
get {
return GetChildByRole(Roles.Identifier).Name;
return GetChildByRole(Roles.Identifier)?.Name ?? string.Empty;
}
set {
SetChildByRole(Roles.Identifier, Identifier.Create(value, TextLocation.Empty));

2
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EnumMemberDeclaration.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -36,7 +36,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[DecompilerAstNode(hasNullNode: false)]
public partial class EnumMemberDeclaration : EntityDeclaration
{
public static readonly Role<Expression> InitializerRole = new Role<Expression>("Initializer", Expression.Null);
public static readonly Role<Expression> InitializerRole = new Role<Expression>("Initializer", null);
public override SymbolKind SymbolKind {
get { return SymbolKind.Field; }

6
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EventDeclaration.cs

@ -64,7 +64,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -64,7 +64,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[EditorBrowsable(EditorBrowsableState.Never)]
public override Identifier NameToken {
get { return Identifier.Null; }
get { return null!; }
set { throw new NotSupportedException(); }
}
}
@ -79,8 +79,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -79,8 +79,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly TokenRole AddKeywordRole = new TokenRole("add");
public static readonly TokenRole RemoveKeywordRole = new TokenRole("remove");
public static readonly Role<Accessor> AddAccessorRole = new Role<Accessor>("AddAccessor", Accessor.Null);
public static readonly Role<Accessor> RemoveAccessorRole = new Role<Accessor>("RemoveAccessor", Accessor.Null);
public static readonly Role<Accessor> AddAccessorRole = new Role<Accessor>("AddAccessor", null);
public static readonly Role<Accessor> RemoveAccessorRole = new Role<Accessor>("RemoveAccessor", null);
public override SymbolKind SymbolKind {
get { return SymbolKind.Event; }

15
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ExtensionDeclaration.cs

@ -49,20 +49,5 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -49,20 +49,5 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public ExtensionDeclaration()
{
}
public override void AcceptVisitor(IAstVisitor visitor)
{
visitor.VisitExtensionDeclaration(this);
}
public override T AcceptVisitor<T>(IAstVisitor<T> visitor)
{
return visitor.VisitExtensionDeclaration(this);
}
public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
{
return visitor.VisitExtensionDeclaration(this, data);
}
}
}

2
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FieldDeclaration.cs

@ -60,7 +60,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -60,7 +60,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[EditorBrowsable(EditorBrowsableState.Never)]
public override Identifier NameToken {
get { return Identifier.Null; }
get { return null!; }
set { throw new NotSupportedException(); }
}
}

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

@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly TokenRole ThisKeywordRole = new TokenRole("this");
public static readonly Role<Accessor> GetterRole = PropertyDeclaration.GetterRole;
public static readonly Role<Accessor> SetterRole = PropertyDeclaration.SetterRole;
public static readonly Role<Expression> ExpressionBodyRole = new Role<Expression>("ExpressionBody", Expression.Null);
public static readonly Role<Expression> ExpressionBodyRole = new Role<Expression>("ExpressionBody", null);
public override SymbolKind SymbolKind {
get { return SymbolKind.Indexer; }
@ -73,7 +73,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -73,7 +73,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[EditorBrowsable(EditorBrowsableState.Never)]
public override Identifier NameToken {
get { return Identifier.Null; }
get { return null!; }
set { throw new NotSupportedException(); }
}

2
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs

@ -324,7 +324,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -324,7 +324,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[EditorBrowsable(EditorBrowsableState.Never)]
public override Identifier NameToken {
get { return Identifier.Null; }
get { return null!; }
set { throw new NotSupportedException(); }
}
}

2
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs

@ -86,7 +86,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -86,7 +86,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
[Slot("Roles.Type")]
public partial AstType? Type { get; set; }
[NameSlot("Roles.Identifier")]
[NameSlot("Roles.Identifier", nullOnEmpty: true)]
public partial string Name { get; set; }
[Slot("Roles.Expression")]

8
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs

@ -44,9 +44,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -44,9 +44,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public static readonly TokenRole GetKeywordRole = new TokenRole("get");
public static readonly TokenRole SetKeywordRole = new TokenRole("set");
public static readonly TokenRole InitKeywordRole = new TokenRole("init");
public static readonly Role<Accessor> GetterRole = new Role<Accessor>("Getter", Accessor.Null);
public static readonly Role<Accessor> SetterRole = new Role<Accessor>("Setter", Accessor.Null);
public static readonly Role<Expression> ExpressionBodyRole = new Role<Expression>("ExpressionBody", Expression.Null);
public static readonly Role<Accessor> GetterRole = new Role<Accessor>("Getter", null);
public static readonly Role<Accessor> SetterRole = new Role<Accessor>("Setter", null);
public static readonly Role<Expression> ExpressionBodyRole = new Role<Expression>("ExpressionBody", null);
public override SymbolKind SymbolKind {
get { return SymbolKind.Property; }
@ -75,7 +75,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -75,7 +75,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public partial Accessor? Setter { get; set; }
[Slot("Roles.Expression")]
public partial Expression Initializer { get; set; }
public partial Expression? Initializer { get; set; }
[Slot("ExpressionBodyRole")]
public partial Expression? ExpressionBody { get; set; }

4
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -2081,14 +2081,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2081,14 +2081,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
else
{
return BlockStatement.Null;
return null;
}
}
Accessor ConvertAccessor(IMethod accessor, MethodSemanticsAttributes kind, Accessibility ownerAccessibility, bool addParameterAttribute)
{
if (accessor == null)
return Accessor.Null;
return null;
Accessor decl = new Accessor();
if (ShowAttributes)
{

2
ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs

@ -393,7 +393,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -393,7 +393,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
// We cannot use checked/unchecked for top-level-expressions.
}
else if (expr.Role.IsValid(Expression.Null))
else if (expr.Role is Role<Expression> || expr.Role is Role<AstNode>)
{
// We use '<' so that expressions are introduced on the deepest level possible (goal 3)
var costIfWrapWithChecked = result.CostInCheckedContext.WrapInCheckedExpr();

2
ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
var memberNames = typeDecl.Members.Select(m => {
var type = m.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole);
return type.IsNull ? m.Name : type + "." + m.Name;
return type is null ? m.Name : type + "." + m.Name;
}).ToHashSet();
// memberNames does not include fields or non-custom events because those
// don't have a single name, but a list of VariableInitializers.

1
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceQueryExpressions.cs

@ -258,6 +258,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -258,6 +258,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// lambda, so this match always succeeds.
bool matched = MatchSimpleLambda(lambda, out parameter, out orderExpression);
Debug.Assert(matched);
Debug.Assert(orderExpression != null);
}
// The chain was validated and every iteration re-matched a simple lambda,
// so the final range-variable parameter is set.

4
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs

@ -97,8 +97,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -97,8 +97,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{
// transform "*(ptr + int)" to "ptr[int]"
IndexerExpression indexer = new IndexerExpression();
indexer.Target = bop.Left.Detach();
indexer.Arguments.Add(bop.Right.Detach());
indexer.Target = bop.Left!.Detach();
indexer.Arguments.Add(bop.Right!.Detach());
indexer.CopyAnnotationsFrom(unaryOperatorExpression);
indexer.CopyAnnotationsFrom(bop);
unaryOperatorExpression.ReplaceWith(indexer);

4
ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs

@ -93,7 +93,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -93,7 +93,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
void DoTransform(Statement? statement, Statement parent)
{
if (statement is null || statement.IsNull)
if (statement is null)
return;
if (context.Settings.AlwaysUseBraces)
{
@ -122,8 +122,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -122,8 +122,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
static void InsertBlock(Statement statement)
{
if (statement.IsNull)
return;
if (!(statement is BlockStatement))
{
var b = new BlockStatement();

2
ICSharpCode.Decompiler/CSharp/Transforms/PrettifyAssignments.cs

@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (rhs is BinaryOperatorExpression binary && assignment.Operator == AssignmentOperatorType.Assign)
{
if (CanConvertToCompoundAssignment(assignment.Left) && assignment.Left.IsMatch(binary.Left)
&& IsImplicitlyConvertible(binary.Right, expectedType))
&& binary.Right != null && IsImplicitlyConvertible(binary.Right, expectedType))
{
assignment.Operator = GetAssignmentOperatorForBinaryOperator(binary.Operator);
if (assignment.Operator != AssignmentOperatorType.Assign)

2
ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs

@ -546,7 +546,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -546,7 +546,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
break;
case PropertyDeclaration pd:
Debug.Assert(pd.IsAutomaticProperty);
if (pd.Initializer.IsNull)
if (pd.Initializer is null)
{
pd.Initializer = initializer.Detach();
}

2
ICSharpCode.Decompiler/IL/ILAmbience.cs

@ -400,7 +400,7 @@ namespace ICSharpCode.Decompiler.IL @@ -400,7 +400,7 @@ namespace ICSharpCode.Decompiler.IL
builder.Append(type.CallingConvention.ToILSyntax());
builder.Append(' ');
}
type.ReturnType.AcceptVisitor(this);
type.ReturnType?.AcceptVisitor(this);
builder.Append(" *(");
bool first = true;
foreach (var p in type.ParameterTypes)

2
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -300,7 +300,7 @@ namespace ICSharpCode.Decompiler @@ -300,7 +300,7 @@ namespace ICSharpCode.Decompiler
// Attach member reference to token only if there's no identifier in the current node.
var member = GetCurrentMemberReference();
var node = nodeStack.Peek();
if (member != null && node.GetChildByRole(Roles.Identifier).IsNull)
if (member != null && node.GetChildByRole(Roles.Identifier) is null)
{
switch (member)
{

2
ILSpy/Languages/CSharpLanguage.cs

@ -627,7 +627,7 @@ namespace ICSharpCode.ILSpy.Languages @@ -627,7 +627,7 @@ namespace ICSharpCode.ILSpy.Languages
}
break;
case PropertyDeclaration pd:
if (pd.Initializer.IsNull)
if (pd.Initializer is null)
{
pd.Remove();
removedSymbols.Add(pd.GetSymbol());

Loading…
Cancel
Save