From 9285a7328d85ff0eac3692753744effc2024ff66 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 17 Jun 2026 08:49:34 +0200 Subject: [PATCH] Delete the Role hierarchy; key the child API on SlotKind Slot identity already lived in node.Slot/CSharpSlotInfo/SlotKind after the storage flip, so the parallel Role/Role child model was redundant. The Role-keyed mutation/query API is reexpressed over SlotKind, and the role-index packing on AstNode flags is gone. Because a node's Slot is now derived from its index in its parent rather than stored on the child, the located-AST reattach in InsertMissingTokensDecorator must capture the child's slot kind before Remove() detaches it. Assisted-by: Claude:claude-opus-4-8:Claude Code --- .../DecompilerSyntaxTreeGenerator.cs | 26 +-- .../CSharp/CSharpDecompiler.cs | 24 +-- .../CSharp/OutputVisitor/CSharpAmbience.cs | 10 +- .../OutputVisitor/CSharpOutputVisitor.cs | 2 +- .../InsertMissingTokensDecorator.cs | 5 +- .../CSharp/Syntax/AstNode.cs | 161 ++++++------------ .../CSharp/Syntax/AstNodeCollection.cs | 22 +-- .../CSharp/Syntax/ComposedType.cs | 4 +- .../CSharp/Syntax/DocumentationReference.cs | 2 - .../Expressions/AnonymousMethodExpression.cs | 4 +- .../AnonymousTypeCreateExpression.cs | 2 +- .../Expressions/ArrayCreateExpression.cs | 2 - .../CSharp/Syntax/Expressions/AsExpression.cs | 4 +- .../Expressions/AssignmentExpression.cs | 2 - .../Expressions/BinaryOperatorExpression.cs | 6 +- .../Syntax/Expressions/CastExpression.cs | 4 +- .../Syntax/Expressions/CheckedExpression.cs | 2 +- .../Expressions/ConditionalExpression.cs | 9 +- .../Expressions/DefaultValueExpression.cs | 2 +- .../Syntax/Expressions/DirectionExpression.cs | 2 +- .../Expressions/IdentifierExpression.cs | 2 +- .../Syntax/Expressions/IndexerExpression.cs | 2 +- .../InterpolatedStringExpression.cs | 1 - .../Expressions/InvocationExpression.cs | 4 +- .../CSharp/Syntax/Expressions/IsExpression.cs | 4 +- .../Syntax/Expressions/LambdaExpression.cs | 2 - .../Expressions/MemberReferenceExpression.cs | 4 +- .../Expressions/ObjectCreateExpression.cs | 5 +- .../Syntax/Expressions/QueryExpression.cs | 11 -- .../Expressions/RecursivePatternExpression.cs | 1 - .../Syntax/Expressions/SizeOfExpression.cs | 2 +- .../Expressions/StackAllocExpression.cs | 1 - .../Syntax/Expressions/SwitchExpression.cs | 3 - .../Syntax/Expressions/ThrowExpression.cs | 2 +- .../Syntax/Expressions/TypeOfExpression.cs | 2 +- .../Expressions/TypeReferenceExpression.cs | 2 +- .../Syntax/Expressions/UncheckedExpression.cs | 2 +- .../Expressions/WithInitializerExpression.cs | 1 - .../CSharp/Syntax/FunctionPointerAstType.cs | 1 - .../Syntax/GeneralScope/AttributeSection.cs | 4 +- .../GeneralScope/NamespaceDeclaration.cs | 4 +- .../GeneralScope/PreProcessorDirective.cs | 1 - .../GeneralScope/TypeParameterDeclaration.cs | 1 - .../GeneralScope/UsingAliasDeclaration.cs | 10 +- .../Syntax/GeneralScope/UsingDeclaration.cs | 5 +- .../CSharp/Syntax/MemberType.cs | 3 +- ICSharpCode.Decompiler/CSharp/Syntax/Role.cs | 112 ------------ ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs | 21 --- .../CSharp/Syntax/SimpleType.cs | 4 +- .../Syntax/Statements/BlockStatement.cs | 5 +- .../Syntax/Statements/CheckedStatement.cs | 2 +- .../CSharp/Syntax/Statements/ForStatement.cs | 2 - .../Syntax/Statements/IfElseStatement.cs | 3 - .../LocalFunctionDeclarationStatement.cs | 3 +- .../Syntax/Statements/ReturnStatement.cs | 2 +- .../Syntax/Statements/SwitchStatement.cs | 2 - .../Syntax/Statements/ThrowStatement.cs | 2 +- .../Syntax/Statements/TryCatchStatement.cs | 4 - .../Syntax/Statements/UncheckedStatement.cs | 2 +- .../Syntax/Statements/UsingStatement.cs | 1 - .../CSharp/Syntax/SyntaxTree.cs | 1 - .../CSharp/Syntax/TupleAstType.cs | 1 - .../TypeMembers/ConstructorDeclaration.cs | 1 - .../Syntax/TypeMembers/EntityDeclaration.cs | 16 +- .../TypeMembers/EnumMemberDeclaration.cs | 1 - .../Syntax/TypeMembers/EventDeclaration.cs | 2 - .../TypeMembers/FixedFieldDeclaration.cs | 1 - .../Syntax/TypeMembers/IndexerDeclaration.cs | 3 - .../Syntax/TypeMembers/MethodDeclaration.cs | 2 +- .../TypeMembers/ParameterDeclaration.cs | 1 - .../Syntax/TypeMembers/PropertyDeclaration.cs | 3 - .../CSharp/Syntax/TypeSystemAstBuilder.cs | 4 +- .../CSharp/Transforms/AddCheckedBlocks.cs | 2 +- .../CSharp/Transforms/DeclareVariables.cs | 8 +- .../CSharp/Transforms/FixNameCollisions.cs | 4 +- .../Transforms/IntroduceUsingDeclarations.cs | 2 +- .../Transforms/PatternStatementTransform.cs | 2 +- ...ransformFieldAndConstructorInitializers.cs | 4 +- .../ICSharpCode.Decompiler.csproj | 1 - .../Output/TextTokenWriter.cs | 2 +- .../CSharpHighlightingTokenWriter.cs | 8 +- 81 files changed, 168 insertions(+), 441 deletions(-) delete mode 100644 ICSharpCode.Decompiler/CSharp/Syntax/Role.cs diff --git a/ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs b/ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs index 9e9ac19ce..c0c7fa743 100644 --- a/ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs +++ b/ICSharpCode.Decompiler.Generators/DecompilerSyntaxTreeGenerator.cs @@ -314,7 +314,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator if (isCollection) { builder.AppendLine($"\tAstNodeCollection<{elementType}>? {field};"); - builder.AppendLine($"\tpublic {(isOverride ? "override " : "")}{partialKw}AstNodeCollection<{elementType}> {name} => {field} ??= new AstNodeCollection<{elementType}>(this, {roleExpr});"); + builder.AppendLine($"\tpublic {(isOverride ? "override " : "")}{partialKw}AstNodeCollection<{elementType}> {name} => {field} ??= new AstNodeCollection<{elementType}>(this, SlotKind.{kindName});"); } else { @@ -322,7 +322,7 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator builder.AppendLine($"\tpublic {(isOverride ? "override " : "")}{partialKw}{type}{(isNullable ? "?" : "")} {name}"); builder.AppendLine("\t{"); builder.AppendLine($"\t\tget => {field}{(isNullable ? "" : "!")};"); - builder.AppendLine($"\t\tset => SetChildNode(ref {field}, value, {roleExpr});"); + builder.AppendLine($"\t\tset => SetChildNode(ref {field}, value);"); builder.AppendLine("\t}"); } builder.AppendLine(); @@ -389,27 +389,13 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator } else { - builder.AppendLine($"\t\tif (i == 0) {{ SetChildNode(ref {FieldName(s.PropertyName)}, ({s.PropertyType}?)value, {s.RoleExpr}); return; }} i -= 1;"); + builder.AppendLine($"\t\tif (i == 0) {{ SetChildNode(ref {FieldName(s.PropertyName)}, ({s.PropertyType}?)value); return; }} i -= 1;"); } } builder.AppendLine("\t\tthrow new System.ArgumentOutOfRangeException(nameof(index));"); builder.AppendLine("\t}"); builder.AppendLine(); - builder.AppendLine("\tinternal override Role GetChildSlot(int index)"); - builder.AppendLine("\t{"); - builder.AppendLine("\t\tint i = index;"); - foreach (var s in slots) - { - if (s.IsCollection) - builder.AppendLine($"\t\t{{ int n = {FieldName(s.PropertyName)}?.Count ?? 0; if (i < n) return {s.RoleExpr}; i -= n; }}"); - else - builder.AppendLine($"\t\tif (i == 0) return {s.RoleExpr}; i -= 1;"); - } - builder.AppendLine("\t\tthrow new System.ArgumentOutOfRangeException(nameof(index));"); - builder.AppendLine("\t}"); - builder.AppendLine(); - // One CSharpSlotInfo static per slot; node.Slot compares against these by object identity. foreach (var s in slots) builder.AppendLine($"\tpublic static readonly CSharpSlotInfo {s.PropertyName}Slot = new CSharpSlotInfo(\"{s.PropertyName}\", typeof({s.ElementType}), {(s.IsCollection ? "true" : "false")}, SlotKind.{s.KindName});"); @@ -431,11 +417,11 @@ internal class DecompilerSyntaxTreeGenerator : IIncrementalGenerator if (slots.Any(s => s.IsCollection)) { - builder.AppendLine("\tinternal override AstNodeCollection? GetCollectionByRole(Role role)"); + builder.AppendLine("\tinternal override AstNodeCollection? GetCollectionByKind(SlotKind kind)"); builder.AppendLine("\t{"); foreach (var s in slots.Where(s => s.IsCollection)) - builder.AppendLine($"\t\tif (role == {s.RoleExpr}) return {s.PropertyName};"); - builder.AppendLine("\t\treturn base.GetCollectionByRole(role);"); + builder.AppendLine($"\t\tif (kind == SlotKind.{s.KindName}) return {s.PropertyName};"); + builder.AppendLine("\t\treturn base.GetCollectionByKind(kind);"); builder.AppendLine("\t}"); builder.AppendLine(); } diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index e711994a3..83355f8f9 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -806,7 +806,7 @@ namespace ICSharpCode.Decompiler.CSharp } currentNamespace = typeDef.Namespace; var typeDecl = DoDecompile(typeDef, decompileRun, decompilationContext.WithCurrentTypeDefinition(typeDef)); - groupNode.AddChild(typeDecl, SyntaxTree.MemberRole); + groupNode.AddChild(typeDecl, SlotKind.Member); } } @@ -1349,11 +1349,11 @@ namespace ICSharpCode.Decompiler.CSharp RemoveAttribute(prop, KnownAttribute.ExtensionMarker); if (propDef.Getter != null) { - RemoveAttribute(prop.GetChildByRole(PropertyDeclaration.GetterRole), KnownAttribute.ExtensionMarker); + RemoveAttribute(prop.GetChildByRole(SlotKind.Getter), KnownAttribute.ExtensionMarker); } if (propDef.Setter != null) { - RemoveAttribute(prop.GetChildByRole(PropertyDeclaration.SetterRole), KnownAttribute.ExtensionMarker); + RemoveAttribute(prop.GetChildByRole(SlotKind.Setter), KnownAttribute.ExtensionMarker); } RunTransforms(syntaxTree, decompileRun, new SimpleTypeResolveContext(propDef.DeclaringTypeDefinition)); break; @@ -1406,7 +1406,7 @@ namespace ICSharpCode.Decompiler.CSharp EntityDeclaration memberDecl, IMethod method, TypeSystemAstBuilder astBuilder) { - if (memberDecl.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole) is not null) + if (memberDecl.GetChildByRole(SlotKind.PrivateImplementationType) is not null) { yield break; // cannot create forwarder for existing explicit interface impl } @@ -1430,9 +1430,9 @@ namespace ICSharpCode.Decompiler.CSharp methodDecl.ReturnType = memberDecl.ReturnType?.Clone(); methodDecl.PrivateImplementationType = astBuilder.ConvertType(m.DeclaringType); methodDecl.Name = m.Name; - methodDecl.TypeParameters.AddRange(memberDecl.GetChildrenByRole(Roles.TypeParameter) + methodDecl.TypeParameters.AddRange(memberDecl.GetChildrenByRole(SlotKind.TypeParameter) .Select(n => (TypeParameterDeclaration)n.Clone())); - methodDecl.Parameters.AddRange(memberDecl.GetChildrenByRole(Roles.Parameter).Select(n => n.Clone())); + methodDecl.Parameters.AddRange(memberDecl.GetChildrenByRole(SlotKind.Parameter).Select(n => n.Clone())); // Constraints are not copied because explicit interface implementations cannot have constraints. CS0460 methodDecl.Body = new BlockStatement(); @@ -1548,7 +1548,7 @@ namespace ICSharpCode.Decompiler.CSharp void FixParameterNames(EntityDeclaration entity) { int i = 0; - foreach (var parameter in entity.GetChildrenByRole(Roles.Parameter)) + foreach (var parameter in entity.GetChildrenByRole(SlotKind.Parameter)) { if (string.IsNullOrWhiteSpace(parameter.Name) && !parameter.Type.IsArgList()) { @@ -1845,11 +1845,11 @@ namespace ICSharpCode.Decompiler.CSharp RemoveAttribute(prop, KnownAttribute.ExtensionMarker); if (p.Getter != null) { - RemoveAttribute(prop.GetChildByRole(PropertyDeclaration.GetterRole), KnownAttribute.ExtensionMarker); + RemoveAttribute(prop.GetChildByRole(SlotKind.Getter), KnownAttribute.ExtensionMarker); } if (p.Setter != null) { - RemoveAttribute(prop.GetChildByRole(PropertyDeclaration.SetterRole), KnownAttribute.ExtensionMarker); + RemoveAttribute(prop.GetChildByRole(SlotKind.Setter), KnownAttribute.ExtensionMarker); } extMemberDecl = prop; break; @@ -2053,7 +2053,7 @@ namespace ICSharpCode.Decompiler.CSharp var commentStatement = new EmptyStatement(); commentStatement.AddTrailingTrivia(new Comment("Invalid MethodBodyBlock: " + ex.Message)); body.Statements.Add(commentStatement); - entityDecl.AddChild(body, Roles.Body); + entityDecl.AddChild(body, SlotKind.Body); return; } var function = ilReader.ReadIL((MethodDefinitionHandle)method.MetadataToken, methodBody, cancellationToken: CancellationToken); @@ -2112,7 +2112,7 @@ namespace ICSharpCode.Decompiler.CSharp body.Statements.Add(warningStatement); } - entityDecl.AddChild(body, Roles.Body); + entityDecl.AddChild(body, SlotKind.Body); } CleanUpMethodDeclaration(entityDecl, body, function, localSettings.DecompileMemberBodies); @@ -2127,7 +2127,7 @@ namespace ICSharpCode.Decompiler.CSharp { int i = parameterOffset; var parameters = function.Variables.Where(v => v.Kind == VariableKind.Parameter).ToDictionary(v => v.Index); - foreach (var parameter in entityDecl.GetChildrenByRole(Roles.Parameter)) + foreach (var parameter in entityDecl.GetChildrenByRole(SlotKind.Parameter)) { if (parameters.TryGetValue(i, out var v)) parameter.AddAnnotation(new ILVariableResolveResult(v, method.Parameters[i].Type)); diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs index 5917fa647..8dd3c768d 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs @@ -123,7 +123,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor if ((ConversionFlags & ConversionFlags.PlaceReturnTypeAfterParameterList) != ConversionFlags.PlaceReturnTypeAfterParameterList && (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) { - var rt = node.GetChildByRole(Roles.Type); + var rt = node.GetChildByRole(SlotKind.Type); if (rt is not null) { rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy)); @@ -150,7 +150,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor } else { - parameters = node.GetChildrenByRole(Roles.Parameter); + parameters = node.GetChildrenByRole(SlotKind.Parameter); } foreach (var param in parameters) { @@ -181,7 +181,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor if ((ConversionFlags & ConversionFlags.PlaceReturnTypeAfterParameterList) == ConversionFlags.PlaceReturnTypeAfterParameterList && (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) { - var rt = node.GetChildByRole(Roles.Type); + var rt = node.GetChildByRole(SlotKind.Type); if (rt is not null) { writer.Space(); @@ -309,7 +309,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor else { writer.WriteIdentifier(node.NameToken); - WriteTypeParameters(node.GetChildrenByRole(Roles.TypeParameter), writer, formattingPolicy); + WriteTypeParameters(node.GetChildrenByRole(SlotKind.TypeParameter), writer, formattingPolicy); } } @@ -412,7 +412,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor writer.WriteIdentifier(Identifier.Create(name)); break; } - WriteTypeParameters(node.GetChildrenByRole(Roles.TypeParameter), writer, formattingPolicy); + WriteTypeParameters(node.GetChildrenByRole(SlotKind.TypeParameter), writer, formattingPolicy); } void WriteTypeParameters(IEnumerable typeParameters, TokenWriter writer, CSharpFormattingOptions formattingPolicy) diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs index b40a52838..33d5cc95f 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -1910,7 +1910,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor public virtual void VisitLabelStatement(LabelStatement labelStatement) { StartNode(labelStatement); - WriteIdentifier(labelStatement.GetChildByRole(Roles.Identifier)); + WriteIdentifier(labelStatement.GetChildByRole(SlotKind.Identifier)); WriteToken(Roles.Colon); bool foundLabelledStatement = false; for (AstNode tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling) diff --git a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs index 2f8997284..b2d2328e6 100644 --- a/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs +++ b/ICSharpCode.Decompiler/CSharp/OutputVisitor/InsertMissingTokensDecorator.cs @@ -91,8 +91,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor foreach (var child in currentList) { System.Diagnostics.Debug.Assert(child.Parent == null || node == child.Parent); + // Slot is derived from the child's index in its parent, so it must be read before + // Remove() detaches the child (which would otherwise leave it as SlotKind.None). + SlotKind kind = child.Slot?.Kind ?? SlotKind.None; child.Remove(); - node.AddChildWithExistingRole(child); + node.AddChildUnsafe(child, kind); } currentList = nodes.Pop(); } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs b/ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs index fe9f51496..06ba9b636 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs @@ -40,22 +40,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: true, hasPatternPlaceholder: true)] public abstract partial 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 RootRole = new Role("Root", null); - AstNode? parent; // Flattened index of this node within its parent's child-index space (-1 when unparented). // Recomputed lazily by the parent (EnsureChildIndices) after a structural mutation. internal int childIndex = -1; - // Flags, from least significant to most significant bits: - // - Role.RoleIndexBits: role index - protected uint flags = RootRole.Index; - // Derived classes may also use a few bits, - // for example Identifier uses 1 bit for IsVerbatim + // Flag bits used by derived classes (e.g. Identifier uses 1 bit for IsVerbatim). + protected uint flags = 0; - const uint roleIndexMask = (1u << Role.RoleIndexBits) - 1; - protected const int AstNodeFlagsUsedBits = Role.RoleIndexBits; + protected const int AstNodeFlagsUsedBits = 0; TextLocation startLocation = TextLocation.Empty; TextLocation endLocation = TextLocation.Empty; @@ -158,28 +151,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax get { return parent; } } - public Role Role { - get { - return Role.GetByIndex(flags & roleIndexMask); - } - set { - if (value == null) - throw new ArgumentNullException(nameof(value)); - if (!value.IsValid(this)) - throw new ArgumentException("This node is not valid in the new role."); - SetRole(value); - } - } - - internal uint RoleIndex { - get { return flags & roleIndexMask; } - } - - void SetRole(Role role) - { - flags = (flags & ~roleIndexMask) | role.Index; - } - public AstNode? NextSibling { get { if (parent == null) @@ -336,20 +307,18 @@ 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. /// - public T GetChildByRole(Role role) where T : AstNode? + public T GetChildByRole(SlotKind kind) where T : AstNode? { - if (role == null) - throw new ArgumentNullException(nameof(role)); int count = GetChildCount(); for (int i = 0; i < count; i++) { - if (GetChildSlot(i) == role) + if (GetChildSlotInfo(i).Kind == kind) { AstNode? c = GetChild(i); - return c != null ? (T)c : role.NullObject; + return c != null ? (T)c : default!; } } - return role.NullObject; + return default!; } public T? GetParent() where T : AstNode @@ -362,20 +331,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return pred != null ? Ancestors.FirstOrDefault(pred) : Ancestors.FirstOrDefault(); } - public AstNodeCollection GetChildrenByRole(Role role) where T : AstNode + public AstNodeCollection GetChildrenByRole(SlotKind kind) where T : AstNode { - if (role == null) - throw new ArgumentNullException(nameof(role)); - AstNodeCollection? collection = GetCollectionByRole(role); - // A node has no children of a role it does not declare a collection slot for. Reads of such - // a role (e.g. the parameters of a non-indexer property) get a detached empty collection; - // writes go through AddChild/SetChildByRole, which reject a missing role. - return collection != null ? (AstNodeCollection)collection : new AstNodeCollection(this, role); + AstNodeCollection? collection = GetCollectionByKind(kind); + // A node has no children of a kind it does not declare a collection slot for. Reads of such + // a kind (e.g. the parameters of a non-indexer property) get a detached empty collection; + // writes go through AddChild/SetChildByRole, which reject a missing slot. + return collection != null ? (AstNodeCollection)collection : new AstNodeCollection(this, kind); } - protected void SetChildByRole(Role role, T? newChild) where T : AstNode + protected void SetChildByRole(SlotKind kind, T? newChild) where T : AstNode { - SetChildByRoleUntyped(role, newChild); + SetChildByRoleUntyped(kind, newChild); } #region Slot storage contract @@ -391,8 +358,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax internal virtual void SetChild(int index, AstNode? value) => throw new ArgumentOutOfRangeException(nameof(index)); - internal virtual Role GetChildSlot(int index) => throw new ArgumentOutOfRangeException(nameof(index)); - // The CSharpSlotInfo for the slot at the given flattened index; generator-emitted per leaf. internal virtual CSharpSlotInfo GetChildSlotInfo(int index) => throw new ArgumentOutOfRangeException(nameof(index)); @@ -409,9 +374,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } - // Returns the collection occupying the slot with the given role, or null if there is none. + // Returns the collection occupying the slot with the given kind, or null if there is none. // Overridden by the generator for nodes that have collection slots. - internal virtual AstNodeCollection? GetCollectionByRole(Role role) => null; + internal virtual AstNodeCollection? GetCollectionByKind(SlotKind kind) => null; // Deep-copies this node's children into the (memberwise-cloned) copy, which initially shares // this node's child references. Overridden by the generator for nodes that have slots. @@ -465,14 +430,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax continue; // empty optional single slot Debug.Assert(child.parent == this, "child's Parent must point back to this node"); Debug.Assert(child.childIndex == i, "child's flattened index must match its slot position"); - Debug.Assert(GetChildSlot(i).IsValid(child), "child's type must be valid in its slot's role"); + Debug.Assert(GetChildSlotInfo(i).ChildType.IsInstanceOfType(child), "child's type must be valid in its slot"); child.CheckInvariant(); } } // Writes a single-slot backing field: detaches the old child, attaches the new one, renumbers. // A null or null-object value empties the slot. Called by generated single-slot property setters. - internal void SetChildNode(ref T? field, T? value, Role role) where T : AstNode + internal void SetChildNode(ref T? field, T? value) where T : AstNode { T? newValue = value; if (field == newValue) @@ -493,14 +458,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } field?.ClearParentAndIndex(); field = newValue; - newValue?.SetParentAndRole(this, role); + newValue?.SetParent(this); InvalidateChildIndices(); } - internal void SetParentAndRole(AstNode newParent, Role role) + internal void SetParent(AstNode newParent) { parent = newParent; - SetRole(role); } internal void ClearParentAndIndex() @@ -510,85 +474,72 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } #endregion - public void AddChild(T child, Role role) where T : AstNode - { - if (role == null) - throw new ArgumentNullException(nameof(role)); - if (child == null) - return; - AddChildUnsafe(child, role); - } - - public void AddChildWithExistingRole(AstNode? child) + public void AddChild(T child, SlotKind kind) where T : AstNode { if (child == null) return; - AddChildUnsafe(child, child.Role); + AddChildUnsafe(child, kind); } /// - /// Adds a child into the slot matching (appending to a collection slot, + /// Adds a child into the slot matching (appending to a collection slot, /// or filling a single slot). /// - internal void AddChildUnsafe(AstNode child, Role role) + internal void AddChildUnsafe(AstNode child, SlotKind kind) { - AstNodeCollection? collection = GetCollectionByRole(role); + AstNodeCollection? collection = GetCollectionByKind(kind); if (collection != null) collection.AddNode(child); else - SetChildByRoleUntyped(role, child); + SetChildByRoleUntyped(kind, child); } // Sets the single slot matching the role (used by the non-generic mutation API). Symmetric with // GetChildByRole, which returns the null object for a role this node does not declare a slot for: // a node has no child of a role it has no slot for, so writing one is a no-op. - internal void SetChildByRoleUntyped(Role role, AstNode? child) + internal void SetChildByRoleUntyped(SlotKind kind, AstNode? child) { int count = GetChildCount(); for (int i = 0; i < count; i++) { - if (GetChildSlot(i) == role) + if (GetChildSlotInfo(i).Kind == kind) { SetChild(i, child); return; } } - throw new InvalidOperationException($"{GetType().Name} has no slot for role '{role}'."); + throw new InvalidOperationException($"{GetType().Name} has no slot of kind '{kind}'."); } - public void InsertChildBefore(AstNode? nextSibling, T child, Role role) where T : AstNode + public void InsertChildBefore(AstNode? nextSibling, T child, SlotKind kind) where T : AstNode { - if (role == null) - throw new ArgumentNullException(nameof(role)); if (child == null) return; - AstNodeCollection? collection = GetCollectionByRole(role); + AstNodeCollection? collection = GetCollectionByKind(kind); if (collection != null) collection.InsertNodeBefore(nextSibling, child); else - SetChildByRoleUntyped(role, child); + SetChildByRoleUntyped(kind, child); } - internal void InsertChildBeforeUnsafe(AstNode nextSibling, AstNode child, Role role) + internal void InsertChildBeforeUnsafe(AstNode nextSibling, AstNode child, SlotKind kind) { - AstNodeCollection? collection = GetCollectionByRole(role); + AstNodeCollection? collection = GetCollectionByKind(kind); if (collection != null) collection.InsertNodeBefore(nextSibling, child); else - SetChildByRoleUntyped(role, child); + SetChildByRoleUntyped(kind, child); } - public void InsertChildAfter(AstNode? prevSibling, T child, Role role) where T : AstNode + public void InsertChildAfter(AstNode? prevSibling, T child, SlotKind kind) where T : AstNode { - if (role == null) - throw new ArgumentNullException(nameof(role)); if (child == null) return; - AstNodeCollection? collection = GetCollectionByRole(role); + AstNodeCollection? collection = GetCollectionByKind(kind); if (collection != null) collection.InsertNodeAfter(prevSibling, child); else - SetChildByRoleUntyped(role, child); + SetChildByRoleUntyped(kind, child); } /// @@ -599,8 +550,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (parent == null) return; parent.EnsureChildIndices(); - Role role = parent.GetChildSlot(childIndex); - AstNodeCollection? collection = parent.GetCollectionByRole(role); + SlotKind kind = parent.GetChildSlotInfo(childIndex).Kind; + AstNodeCollection? collection = parent.GetCollectionByKind(kind); if (collection != null) collection.RemoveNode(this); else @@ -624,12 +575,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax throw new InvalidOperationException("Cannot replace the root node"); } parent.EnsureChildIndices(); - Role role = parent.GetChildSlot(childIndex); - // Because this method doesn't statically check the new node's type with the role, + CSharpSlotInfo slot = parent.GetChildSlotInfo(childIndex); + // Because this method doesn't statically check the new node's type with the slot, // we perform a runtime test: - if (!role.IsValid(newNode)) + if (!slot.ChildType.IsInstanceOfType(newNode)) { - throw new ArgumentException(string.Format("The new node '{0}' is not valid in the role {1}", newNode.GetType().Name, role.ToString()), nameof(newNode)); + throw new ArgumentException(string.Format("The new node '{0}' is not valid in the slot {1}", newNode.GetType().Name, slot.ToString()), nameof(newNode)); } if (newNode.parent != null) { @@ -658,7 +609,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } AstNode oldParent = parent; AstNode? oldSuccessor = NextSibling; - Role oldRole = this.Role; + CSharpSlotInfo? oldSlot = this.Slot; + SlotKind oldKind = oldSlot?.Kind ?? SlotKind.None; Remove(); AstNode? replacement = replaceFunction(this); if (oldSuccessor != null && oldSuccessor.parent != oldParent) @@ -667,15 +619,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { if (replacement.parent != null) throw new InvalidOperationException("replace function must return the root of a tree"); - if (!oldRole.IsValid(replacement)) + if (oldSlot != null && !oldSlot.ChildType.IsInstanceOfType(replacement)) { - throw new InvalidOperationException(string.Format("The new node '{0}' is not valid in the role {1}", replacement.GetType().Name, oldRole.ToString())); + throw new InvalidOperationException(string.Format("The new node '{0}' is not valid in the slot {1}", replacement.GetType().Name, oldSlot.ToString())); } if (oldSuccessor != null) - oldParent.InsertChildBeforeUnsafe(oldSuccessor, replacement, oldRole); + oldParent.InsertChildBeforeUnsafe(oldSuccessor, replacement, oldKind); else - oldParent.AddChildUnsafe(replacement, oldRole); + oldParent.AddChildUnsafe(replacement, oldKind); } return replacement; } @@ -786,17 +738,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax prev = prev.GetPrevNode(); return prev; } - // filters all non c# nodes (comments, white spaces or pre processor directives) + // Comments and directives are trivia, not sibling nodes, so the previous sibling is always a C# node. public AstNode? GetCSharpNodeBefore(AstNode node) { - var n = node.PrevSibling; - while (n != null) - { - if (n.Role != Roles.Comment) - return n; - n = n.GetPrevNode(); - } - return null; + return node.PrevSibling; } /// diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs b/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs index fbf95a613..966bcaff4 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/AstNodeCollection.cs @@ -72,13 +72,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax where T : AstNode { readonly AstNode parent; - readonly Role role; + readonly SlotKind kind; readonly List list = new List(); - public AstNodeCollection(AstNode parent, Role role) + public AstNodeCollection(AstNode parent, SlotKind kind) { this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); - this.role = role ?? throw new ArgumentNullException(nameof(role)); + this.kind = kind; } public int Count { @@ -97,7 +97,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ValidateNewChild(value); old.ClearParentAndIndex(); list[index] = value; - value.SetParentAndRole(parent, role); + value.SetParent(parent); parent.InvalidateChildIndices(); } } @@ -118,7 +118,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return; ValidateNewChild(element); list.Add(element); - element.SetParentAndRole(parent, role); + element.SetParent(parent); parent.InvalidateChildIndices(); } @@ -169,7 +169,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public bool Contains(T element) { - return element != null && element.Parent == parent && element.RoleIndex == role.Index; + return element != null && element.Parent == parent && list.Contains(element); } public int IndexOf(T element) @@ -247,7 +247,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax foreach (T item in list) if (predicate == null || predicate(item)) return item; - return role.NullObject; + return null!; } /// @@ -256,7 +256,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax /// public T LastOrNullObject(Func? predicate = null) { - T result = role.NullObject; + T result = null!; foreach (T item in list) if (predicate == null || predicate(item)) result = item; @@ -289,12 +289,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax #region Equals and GetHashCode implementation public override int GetHashCode() { - return parent.GetHashCode() ^ role.GetHashCode(); + return parent.GetHashCode() ^ kind.GetHashCode(); } public override bool Equals(object? obj) { - return obj is AstNodeCollection other && this.parent == other.parent && this.role == other.role; + return obj is AstNodeCollection other && this.parent == other.parent && this.kind == other.kind; } #endregion @@ -322,7 +322,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return; ValidateNewChild(newItem); list.Insert(index, newItem); - newItem.SetParentAndRole(parent, role); + newItem.SetParent(parent); parent.InvalidateChildIndices(); } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs index a462c87df..9fd4fd617 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs @@ -41,12 +41,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class ComposedType : AstType { - public static readonly Role AttributeRole = EntityDeclaration.AttributeRole; public static readonly TokenRole RefRole = new TokenRole("ref"); 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 ArraySpecifierRole = new Role("ArraySpecifier", null); [Slot("AttributeRole")] public partial AstNodeCollection Attributes { get; } @@ -120,7 +118,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public override AstType MakeArrayType(int dimensions) { - InsertChildBefore(this.ArraySpecifiers.FirstOrDefault(), new ArraySpecifier(dimensions), ArraySpecifierRole); + InsertChildBefore(this.ArraySpecifiers.FirstOrDefault(), new ArraySpecifier(dimensions), SlotKind.ArraySpecifier); return this; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs b/ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs index e0efe131a..b9418a490 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs @@ -34,8 +34,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class DocumentationReference : AstNode { - public static readonly Role DeclaringTypeRole = new Role("DeclaringType", null); - public static readonly Role ConversionOperatorReturnTypeRole = new Role("ConversionOperatorReturnType", null); SymbolKind symbolKind; OperatorType operatorType; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousMethodExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousMethodExpression.cs index c6e06c254..0f3ac3dc9 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousMethodExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousMethodExpression.cs @@ -70,10 +70,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax hasParameterList = true; foreach (var parameter in parameters) { - AddChild(parameter, Roles.Parameter); + AddChild(parameter, SlotKind.Parameter); } } - AddChild(body, Roles.Body); + AddChild(body, SlotKind.Body); } public AnonymousMethodExpression(BlockStatement body, params ParameterDeclaration[] parameters) : this(body, (IEnumerable)parameters) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousTypeCreateExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousTypeCreateExpression.cs index 1a08fead2..4726008c2 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousTypeCreateExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousTypeCreateExpression.cs @@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { foreach (var ini in initializers) { - AddChild(ini, Roles.Expression); + AddChild(ini, SlotKind.Expression); } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs index a3264906d..6ac4838b0 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ArrayCreateExpression.cs @@ -27,8 +27,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class ArrayCreateExpression : Expression { public readonly static TokenRole NewKeywordRole = new TokenRole("new"); - public readonly static Role AdditionalArraySpecifierRole = new Role("AdditionalArraySpecifier", null); - public readonly static Role InitializerRole = new Role("Initializer", null); [Slot("Roles.Type")] public partial AstType? Type { get; set; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AsExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AsExpression.cs index e7f0eb3b4..69793169c 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AsExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AsExpression.cs @@ -46,8 +46,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public AsExpression(Expression expression, AstType type) { - AddChild(expression, Roles.Expression); - AddChild(type, Roles.Type); + AddChild(expression, SlotKind.Expression); + AddChild(type, SlotKind.Type); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs index a8ffe69e0..74fb6a413 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs @@ -38,8 +38,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class AssignmentExpression : Expression { // reuse roles from BinaryOperatorExpression - public readonly static Role LeftRole = BinaryOperatorExpression.LeftRole; - public readonly static Role RightRole = BinaryOperatorExpression.RightRole; public readonly static TokenRole AssignRole = new TokenRole("="); public readonly static TokenRole AddRole = new TokenRole("+="); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs index 5851aee3b..3b0dfb916 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/BinaryOperatorExpression.cs @@ -62,8 +62,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public readonly static TokenRole RangeRole = new TokenRole(".."); public readonly static TokenRole IsKeywordRole = IsExpression.IsKeywordRole; - public readonly static Role LeftRole = new Role("Left", null); - public readonly static Role RightRole = new Role("Right", null); public BinaryOperatorExpression() { @@ -81,10 +79,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax set; } - [Slot(nameof(LeftRole))] + [Slot("LeftRole")] public partial Expression? Left { get; set; } - [Slot(nameof(RightRole))] + [Slot("RightRole")] public partial Expression? Right { get; set; } public static TokenRole GetOperatorRole(BinaryOperatorType op) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CastExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CastExpression.cs index 3248d97ce..a73f13e17 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CastExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CastExpression.cs @@ -43,8 +43,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public CastExpression(AstType castToType, Expression expression) { - AddChild(castToType, Roles.Type); - AddChild(expression, Roles.Expression); + AddChild(castToType, SlotKind.Type); + AddChild(expression, SlotKind.Expression); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CheckedExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CheckedExpression.cs index 597b071a0..deb31ba32 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CheckedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/CheckedExpression.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public CheckedExpression(Expression expression) { - AddChild(expression, Roles.Expression); + AddChild(expression, SlotKind.Expression); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ConditionalExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ConditionalExpression.cs index 54aa91ecb..7cc5f6ce6 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ConditionalExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ConditionalExpression.cs @@ -32,11 +32,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class ConditionalExpression : Expression { - public readonly static Role ConditionRole = Roles.Condition; public readonly static TokenRole QuestionMarkRole = new TokenRole("?"); - public readonly static Role TrueRole = new Role("True", null); public readonly static TokenRole ColonRole = Roles.Colon; - public readonly static Role FalseRole = new Role("False", null); [Slot("ConditionRole")] public partial Expression Condition { get; set; } @@ -53,9 +50,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public ConditionalExpression(Expression condition, Expression trueExpression, Expression falseExpression) { - AddChild(condition, ConditionRole); - AddChild(trueExpression, TrueRole); - AddChild(falseExpression, FalseRole); + AddChild(condition, SlotKind.Condition); + AddChild(trueExpression, SlotKind.True); + AddChild(falseExpression, SlotKind.False); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DefaultValueExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DefaultValueExpression.cs index 3b31797a4..893de1a67 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DefaultValueExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DefaultValueExpression.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public DefaultValueExpression(AstType type) { - AddChild(type, Roles.Type); + AddChild(type, SlotKind.Type); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DirectionExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DirectionExpression.cs index 1bfec8d17..6c32152f2 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DirectionExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/DirectionExpression.cs @@ -59,7 +59,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public DirectionExpression(FieldDirection direction, Expression expression) { this.FieldDirection = direction; - AddChild(expression, Roles.Expression); + AddChild(expression, SlotKind.Expression); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IdentifierExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IdentifierExpression.cs index db16890f7..f9b1f6657 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IdentifierExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IdentifierExpression.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public IdentifierExpression(string identifier, TextLocation location) { - SetChildByRole(Roles.Identifier, Decompiler.CSharp.Syntax.Identifier.Create(identifier, location)); + SetChildByRole(SlotKind.Identifier, Decompiler.CSharp.Syntax.Identifier.Create(identifier, location)); } [NameSlot("Roles.Identifier")] diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IndexerExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IndexerExpression.cs index ae17f35a4..cfd1bd211 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IndexerExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IndexerExpression.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { foreach (var arg in arguments) { - AddChild(arg, Roles.Argument); + AddChild(arg, SlotKind.Argument); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InterpolatedStringExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InterpolatedStringExpression.cs index e2cc9c75c..4a76c31cb 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InterpolatedStringExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InterpolatedStringExpression.cs @@ -36,7 +36,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: true)] public abstract partial class InterpolatedStringContent : AstNode { - public new static readonly Role Role = new Role("InterpolatedStringContent", null); } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InvocationExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InvocationExpression.cs index a35d915c2..6f0966553 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InvocationExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/InvocationExpression.cs @@ -46,12 +46,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public InvocationExpression(Expression target, IEnumerable arguments) { - AddChild(target, Roles.TargetExpression); + AddChild(target, SlotKind.TargetExpression); if (arguments != null) { foreach (var arg in arguments) { - AddChild(arg, Roles.Argument); + AddChild(arg, SlotKind.Argument); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IsExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IsExpression.cs index 5ad38ff45..04e7ef7f9 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IsExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/IsExpression.cs @@ -47,8 +47,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public IsExpression(Expression expression, AstType type) { - AddChild(expression, Roles.Expression); - AddChild(type, Roles.Type); + AddChild(expression, SlotKind.Expression); + AddChild(type, SlotKind.Type); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/LambdaExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/LambdaExpression.cs index c66f501e0..b466a9db6 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/LambdaExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/LambdaExpression.cs @@ -32,9 +32,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class LambdaExpression : Expression { - public static readonly Role AttributeRole = new Role("Attribute", null); public readonly static TokenRole AsyncModifierRole = new TokenRole("async"); - public static readonly Role BodyRole = new Role("Body", null); bool isAsync; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/MemberReferenceExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/MemberReferenceExpression.cs index 1097efc7e..eb6fd1c43 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/MemberReferenceExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/MemberReferenceExpression.cs @@ -49,13 +49,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public MemberReferenceExpression(Expression target, string memberName, IEnumerable arguments = null) { - AddChild(target, Roles.TargetExpression); + AddChild(target, SlotKind.TargetExpression); MemberName = memberName; if (arguments != null) { foreach (var arg in arguments) { - AddChild(arg, Roles.TypeArgument); + AddChild(arg, SlotKind.TypeArgument); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ObjectCreateExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ObjectCreateExpression.cs index aa7500ee6..02057f884 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ObjectCreateExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ObjectCreateExpression.cs @@ -37,7 +37,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class ObjectCreateExpression : Expression { public readonly static TokenRole NewKeywordRole = new TokenRole("new"); - public readonly static Role InitializerRole = ArrayCreateExpression.InitializerRole; [Slot("Roles.Type")] public partial AstType Type { get; set; } @@ -54,12 +53,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public ObjectCreateExpression(AstType type, IEnumerable? arguments = null) { - AddChild(type, Roles.Type); + AddChild(type, SlotKind.Type); if (arguments != null) { foreach (var arg in arguments) { - AddChild(arg, Roles.Argument); + AddChild(arg, SlotKind.Argument); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs index 7880b5833..b74def800 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/QueryExpression.cs @@ -26,7 +26,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: true)] public partial class QueryExpression : Expression { - public static readonly Role ClauseRole = new Role("Clause", null); [Slot("ClauseRole")] public partial AstNodeCollection Clauses { get; } @@ -45,7 +44,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class QueryContinuationClause : QueryClause { - public static readonly Role PrecedingQueryRole = new Role("PrecedingQuery", null); public static readonly TokenRole IntoKeywordRole = new TokenRole("into"); [Slot("PrecedingQueryRole")] @@ -115,16 +113,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class QueryJoinClause : QueryClause { public static readonly TokenRole JoinKeywordRole = new TokenRole("join"); - public static readonly Role TypeRole = Roles.Type; - public static readonly Role JoinIdentifierRole = Roles.Identifier; public static readonly TokenRole InKeywordRole = new TokenRole("in"); - public static readonly Role InExpressionRole = Roles.Expression; public static readonly TokenRole OnKeywordRole = new TokenRole("on"); - public static readonly Role OnExpressionRole = new Role("OnExpression", null); public static readonly TokenRole EqualsKeywordRole = new TokenRole("equals"); - public static readonly Role EqualsExpressionRole = new Role("EqualsExpression", null); public static readonly TokenRole IntoKeywordRole = new TokenRole("into"); - public static readonly Role IntoIdentifierRole = new Role("IntoIdentifier", null); // Derived from IntoIdentifier (which DoMatch already compares); exclude it to avoid a redundant compare. [ExcludeFromMatch] @@ -158,7 +150,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class QueryOrderClause : QueryClause { public static readonly TokenRole OrderbyKeywordRole = new TokenRole("orderby"); - public static readonly Role OrderingRole = new Role("Ordering", null); [Slot("OrderingRole")] public partial AstNodeCollection Orderings { get; } @@ -208,9 +199,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class QueryGroupClause : QueryClause { public static readonly TokenRole GroupKeywordRole = new TokenRole("group"); - public static readonly Role ProjectionRole = new Role("Projection", null); public static readonly TokenRole ByKeywordRole = new TokenRole("by"); - public static readonly Role KeyRole = new Role("Key", null); [Slot("ProjectionRole")] public partial Expression Projection { get; set; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/RecursivePatternExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/RecursivePatternExpression.cs index 0f9772001..de17292f7 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/RecursivePatternExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/RecursivePatternExpression.cs @@ -31,7 +31,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class RecursivePatternExpression : Expression { - public static readonly Role SubPatternRole = new Role("SubPattern", null); [Slot("Roles.Type")] public partial AstType? Type { get; set; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SizeOfExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SizeOfExpression.cs index dadace16b..d718d8435 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SizeOfExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SizeOfExpression.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public SizeOfExpression(AstType type) { - AddChild(type, Roles.Type); + AddChild(type, SlotKind.Type); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/StackAllocExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/StackAllocExpression.cs index 21273412e..ec3cc4559 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/StackAllocExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/StackAllocExpression.cs @@ -42,7 +42,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class StackAllocExpression : Expression { public readonly static TokenRole StackallocKeywordRole = new TokenRole("stackalloc"); - public readonly static Role InitializerRole = new Role("Initializer", null); [Slot("Roles.Type")] public partial AstType? Type { get; set; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs index dcdda02a8..e997da991 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/SwitchExpression.cs @@ -26,7 +26,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class SwitchExpression : Expression { public static readonly TokenRole SwitchKeywordRole = new TokenRole("switch"); - public static readonly Role SwitchSectionRole = new Role("SwitchSection", null); [Slot("Roles.Expression")] public partial Expression Expression { get; set; } @@ -41,8 +40,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class SwitchExpressionSection : AstNode { - public static readonly Role PatternRole = new Role("Pattern", null); - public static readonly Role BodyRole = new Role("Body", null); [Slot("PatternRole")] public partial Expression Pattern { get; set; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThrowExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThrowExpression.cs index 0c5e4c8d3..eef458e23 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThrowExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/ThrowExpression.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public ThrowExpression(Expression expression) { - AddChild(expression, Roles.Expression); + AddChild(expression, SlotKind.Expression); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeOfExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeOfExpression.cs index 39381f811..cee38364c 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeOfExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeOfExpression.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public TypeOfExpression(AstType type) { - AddChild(type, Roles.Type); + AddChild(type, SlotKind.Type); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeReferenceExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeReferenceExpression.cs index 8de06c4d0..63fb42364 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeReferenceExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/TypeReferenceExpression.cs @@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public TypeReferenceExpression(AstType type) { - AddChild(type, Roles.Type); + AddChild(type, SlotKind.Type); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UncheckedExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UncheckedExpression.cs index 60254a62d..070aaabd1 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UncheckedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/UncheckedExpression.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public UncheckedExpression(Expression expression) { - AddChild(expression, Roles.Expression); + AddChild(expression, SlotKind.Expression); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/WithInitializerExpression.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/WithInitializerExpression.cs index 32459bab7..e52eb7db9 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/WithInitializerExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Expressions/WithInitializerExpression.cs @@ -26,7 +26,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class WithInitializerExpression : Expression { public readonly static TokenRole WithKeywordRole = new TokenRole("with"); - public readonly static Role InitializerRole = ArrayCreateExpression.InitializerRole; [Slot("Roles.Expression")] public partial Expression Expression { get; set; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerAstType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerAstType.cs index 87a542278..5bd47b590 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerAstType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerAstType.cs @@ -33,7 +33,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class FunctionPointerAstType : AstType { public static readonly TokenRole PointerRole = new TokenRole("*"); - public static readonly Role CallingConventionRole = new Role("CallConv", null); public bool HasUnmanagedCallingConvention { get; set; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/AttributeSection.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/AttributeSection.cs index 999338c42..ae95031fe 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/AttributeSection.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/AttributeSection.cs @@ -35,10 +35,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public string AttributeTarget { get { - return GetChildByRole(Roles.Identifier)?.Name ?? string.Empty; + return GetChildByRole(SlotKind.Identifier)?.Name ?? string.Empty; } set { - SetChildByRole(Roles.Identifier, Identifier.Create(value)); + SetChildByRole(SlotKind.Identifier, Identifier.Create(value)); } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/NamespaceDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/NamespaceDeclaration.cs index d250f8565..36c3b04e1 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/NamespaceDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/NamespaceDeclaration.cs @@ -39,8 +39,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class NamespaceDeclaration : AstNode { - public static readonly Role MemberRole = SyntaxTree.MemberRole; - public static readonly Role NamespaceNameRole = new Role("NamespaceName", null); public bool IsFileScoped { get; set; } @@ -123,7 +121,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public void AddMember(AstNode child) { - AddChild(child, MemberRole); + AddChild(child, SlotKind.Member); } } }; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs index f1073b0b1..c677cba17 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/PreProcessorDirective.cs @@ -67,7 +67,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class PragmaWarningPreprocessorDirective : PreProcessorDirective { - public static readonly Role WarningRole = new Role("Warning", null); public static readonly TokenRole PragmaKeywordRole = new TokenRole("#pragma"); public static readonly TokenRole WarningKeywordRole = new TokenRole("warning"); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeParameterDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeParameterDeclaration.cs index f9ffcc200..4e50c3ae5 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeParameterDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeParameterDeclaration.cs @@ -29,7 +29,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class TypeParameterDeclaration : AstNode { - public static readonly Role AttributeRole = EntityDeclaration.AttributeRole; public static readonly TokenRole OutVarianceKeywordRole = new TokenRole("out"); public static readonly TokenRole InVarianceKeywordRole = new TokenRole("in"); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingAliasDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingAliasDeclaration.cs index 0fd0bc03e..28260f80f 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingAliasDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingAliasDeclaration.cs @@ -33,8 +33,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class UsingAliasDeclaration : AstNode { public static readonly TokenRole UsingKeywordRole = new TokenRole("using"); - public static readonly Role AliasRole = new Role("Alias", null); - public static readonly Role ImportRole = UsingDeclaration.ImportRole; [NameSlot("AliasRole")] public partial string Alias { get; set; } @@ -48,14 +46,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public UsingAliasDeclaration(string alias, string nameSpace) { - AddChild(Identifier.Create(alias), AliasRole); - AddChild(new SimpleType(nameSpace), ImportRole); + AddChild(Identifier.Create(alias), SlotKind.Alias); + AddChild(new SimpleType(nameSpace), SlotKind.Import); } public UsingAliasDeclaration(string alias, AstType import) { - AddChild(Identifier.Create(alias), AliasRole); - AddChild(import, ImportRole); + AddChild(Identifier.Create(alias), SlotKind.Alias); + AddChild(import, SlotKind.Import); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingDeclaration.cs index 3f7eeb27a..6b01d3f60 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/UsingDeclaration.cs @@ -41,7 +41,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class UsingDeclaration : AstNode { public static readonly TokenRole UsingKeywordRole = new TokenRole("using"); - public static readonly Role ImportRole = new Role("Import", null); [Slot("ImportRole")] public partial AstType Import { get; set; } @@ -84,12 +83,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public UsingDeclaration(string nameSpace) { - AddChild(AstType.Create(nameSpace), ImportRole); + AddChild(AstType.Create(nameSpace), SlotKind.Import); } public UsingDeclaration(AstType import) { - AddChild(import, ImportRole); + AddChild(import, SlotKind.Import); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs index 09b3d080a..a50a3448c 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs @@ -34,7 +34,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class MemberType : AstType { - public static readonly Role TargetRole = new Role("Target", null); bool isDoubleColon; @@ -70,7 +69,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.MemberName = memberName; foreach (var arg in typeArguments) { - AddChild(arg, Roles.TypeArgument); + AddChild(arg, SlotKind.TypeArgument); } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Role.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Role.cs deleted file mode 100644 index a27b2773c..000000000 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Role.cs +++ /dev/null @@ -1,112 +0,0 @@ -// 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 -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// 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.Threading; - -namespace ICSharpCode.Decompiler.CSharp.Syntax -{ - /// - /// Represents the role a node plays within its parent. - /// - public abstract class Role - { - public const int RoleIndexBits = 9; - - static readonly Role[] roles = new Role[1 << RoleIndexBits]; - static int nextRoleIndex = 0; - - readonly uint index; - - public uint Index { - get { return index; } - } - - // don't allow NRefactory consumers to derive from Role - internal Role() - { - this.index = (uint)Interlocked.Increment(ref nextRoleIndex); - if (this.index >= roles.Length) - throw new InvalidOperationException("Too many roles"); - roles[this.index] = this; - } - - /// - /// Gets whether the specified node is valid in this role. - /// - public abstract bool IsValid(object node); - - /// - /// Gets the role's null object as a non-generic reference, or null if the role has none. - /// Used by the transitional slot layer, which works with the non-generic base type. - /// - internal abstract object? NullObjectUntyped { get; } - - /// - /// Gets the role with the specified index. - /// - public static Role GetByIndex(uint index) - { - return roles[index]; - } - } - - /// - /// Represents the role a node plays within its parent. - /// All nodes with this role have type T. - /// - public class Role : Role where T : class? - { - readonly string name; // helps with debugging the AST - readonly T nullObject; - - /// - /// Gets the null object used when there's no node with this role. - /// Not every role has a null object; this property returns null for roles without a null object. - /// - /// - /// Roles used for non-collections should always have a null object, so that no AST property returns null. - /// However, if a role used for collections only, it may leave out the null object. - /// - public T NullObject { - get { return nullObject; } - } - - internal override object? NullObjectUntyped => nullObject; - - public override bool IsValid(object node) - { - return node is T; - } - - public Role(string name, T? nullObject) - { - this.name = name ?? throw new ArgumentNullException(nameof(name)); - // Roles used only for collections may omit the null object (pass null); NullObject then - // returns null, matching the documented contract. Single-value roles always pass one. - this.nullObject = nullObject!; - } - - public override string ToString() - { - return name; - } - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs index 3dc9acd32..bc26b18d6 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Roles.cs @@ -28,25 +28,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public static class Roles { - public static readonly Role Root = AstNode.RootRole; // some pre defined constants for common roles - public static readonly Role Identifier = new Role("Identifier", null); - public static readonly Role Body = new Role("Body", null); - public static readonly Role Parameter = new Role("Parameter", null); - public static readonly Role Argument = new Role("Argument", null); - public static readonly Role Type = new Role("Type", null); - public static readonly Role Expression = new Role("Expression", null); - public static readonly Role TargetExpression = new Role("Target", null); - public readonly static Role Condition = new Role("Condition", null); - public static readonly Role TypeParameter = new Role("TypeParameter", null); - public static readonly Role TypeArgument = new Role("TypeArgument", null); - public readonly static Role Constraint = new Role("Constraint", null); - public static readonly Role Variable = new Role("Variable", null); - public static readonly Role EmbeddedStatement = new Role("EmbeddedStatement", null); - public readonly static Role TypeMemberRole = new Role("TypeMember", null); - public static readonly Role VariableDesignationRole = new Role("VariableDesignation", null); // some pre defined constants for most used punctuation public static readonly TokenRole LPar = new TokenRole("("); @@ -64,15 +48,10 @@ 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 = new Role("Comment", null); - public static readonly Role PreProcessorDirective = new Role("PreProcessorDirective", null); - public readonly static Role BaseType = new Role("BaseType", null); - public static readonly Role Attribute = new Role("Attribute", null); public readonly static TokenRole WhereKeyword = new TokenRole("where"); - public readonly static Role ConstraintTypeParameter = new Role("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"); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs index be57b9d51..42c1f4365 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public SimpleType(string identifier, TextLocation location) { - SetChildByRole(Roles.Identifier, Syntax.Identifier.Create(identifier, location)); + SetChildByRole(SlotKind.Identifier, Syntax.Identifier.Create(identifier, location)); } public SimpleType(string identifier, IEnumerable typeArguments) @@ -58,7 +58,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax this.Identifier = identifier; foreach (var arg in typeArguments) { - AddChild(arg, Roles.TypeArgument); + AddChild(arg, SlotKind.TypeArgument); } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BlockStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BlockStatement.cs index 9d4267497..fad088956 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BlockStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/BlockStatement.cs @@ -34,19 +34,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: true, hasPatternPlaceholder: true)] public partial class BlockStatement : Statement, IEnumerable { - public static readonly Role StatementRole = new Role("Statement", null); [Slot("StatementRole")] public partial AstNodeCollection Statements { get; } public void Add(Statement statement) { - AddChild(statement, StatementRole); + AddChild(statement, SlotKind.Statement); } public void Add(Expression expression) { - AddChild(new ExpressionStatement(expression), StatementRole); + AddChild(new ExpressionStatement(expression), SlotKind.Statement); } IEnumerator IEnumerable.GetEnumerator() diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/CheckedStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/CheckedStatement.cs index dffd86f0e..a4d22e088 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/CheckedStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/CheckedStatement.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public CheckedStatement(BlockStatement body) { - AddChild(body, Roles.Body); + AddChild(body, SlotKind.Body); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForStatement.cs index dc19b9241..acdcc2182 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ForStatement.cs @@ -35,8 +35,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class ForStatement : Statement { public static readonly TokenRole ForKeywordRole = new TokenRole("for"); - public readonly static Role InitializerRole = new Role("Initializer", null); - public readonly static Role IteratorRole = new Role("Iterator", null); /// /// Gets the list of initializer statements. diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/IfElseStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/IfElseStatement.cs index 544976450..d92245082 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/IfElseStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/IfElseStatement.cs @@ -35,10 +35,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class IfElseStatement : Statement { public readonly static TokenRole IfKeywordRole = new TokenRole("if"); - public readonly static Role ConditionRole = Roles.Condition; - public readonly static Role TrueRole = new Role("True", null); public readonly static TokenRole ElseKeywordRole = new TokenRole("else"); - public readonly static Role FalseRole = new Role("False", null); [Slot("ConditionRole")] public partial Expression Condition { get; set; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs index adbb0e20d..d0e75c305 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/LocalFunctionDeclarationStatement.cs @@ -24,14 +24,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class LocalFunctionDeclarationStatement : Statement { - public static readonly Role MethodDeclarationRole = new Role("Method", null); [Slot("MethodDeclarationRole")] public partial MethodDeclaration Declaration { get; set; } public LocalFunctionDeclarationStatement(MethodDeclaration methodDeclaration) { - AddChild(methodDeclaration, MethodDeclarationRole); + AddChild(methodDeclaration, SlotKind.MethodDeclaration); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ReturnStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ReturnStatement.cs index 7face432c..6c58834f1 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ReturnStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ReturnStatement.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public ReturnStatement(Expression returnExpression) { - AddChild(returnExpression, Roles.Expression); + AddChild(returnExpression, SlotKind.Expression); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs index e4e013b8d..85547eeea 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/SwitchStatement.cs @@ -35,7 +35,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class SwitchStatement : Statement { public static readonly TokenRole SwitchKeywordRole = new TokenRole("switch"); - public static readonly Role SwitchSectionRole = new Role("SwitchSection", null); [Slot("Roles.Expression")] public partial Expression Expression { get; set; } @@ -50,7 +49,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false, hasPatternPlaceholder: true)] public partial class SwitchSection : AstNode { - public static readonly Role CaseLabelRole = new Role("CaseLabel", null); [Slot("CaseLabelRole")] public partial AstNodeCollection CaseLabels { get; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ThrowStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ThrowStatement.cs index e2234388a..05a851c4b 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ThrowStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/ThrowStatement.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public ThrowStatement(Expression expression) { - AddChild(expression, Roles.Expression); + AddChild(expression, SlotKind.Expression); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/TryCatchStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/TryCatchStatement.cs index 9e3a2ac94..a2ecd1682 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/TryCatchStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/TryCatchStatement.cs @@ -35,10 +35,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class TryCatchStatement : Statement { public static readonly TokenRole TryKeywordRole = new TokenRole("try"); - public static readonly Role TryBlockRole = new Role("TryBlock", null); - public static readonly Role CatchClauseRole = new Role("CatchClause", null); public static readonly TokenRole FinallyKeywordRole = new TokenRole("finally"); - public static readonly Role FinallyBlockRole = new Role("FinallyBlock", null); [Slot("TryBlockRole")] public partial BlockStatement TryBlock { get; set; } @@ -58,7 +55,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public static readonly TokenRole CatchKeywordRole = new TokenRole("catch"); public static readonly TokenRole WhenKeywordRole = new TokenRole("when"); - public static readonly Role ConditionRole = Roles.Condition; public static readonly TokenRole CondLPar = new TokenRole("("); public static readonly TokenRole CondRPar = new TokenRole(")"); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UncheckedStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UncheckedStatement.cs index aefab1374..dbb507516 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UncheckedStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UncheckedStatement.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public UncheckedStatement(BlockStatement body) { - AddChild(body, Roles.Body); + AddChild(body, SlotKind.Body); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UsingStatement.cs b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UsingStatement.cs index ce92200fc..e0ad6f942 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UsingStatement.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/Statements/UsingStatement.cs @@ -34,7 +34,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public static readonly TokenRole UsingKeywordRole = new TokenRole("using"); public static readonly TokenRole AwaitRole = UnaryOperatorExpression.AwaitRole; - public static readonly Role ResourceAcquisitionRole = new Role("ResourceAcquisition", null); public bool IsAsync { get; set; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs b/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs index da0a3cad4..f45e6f034 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs @@ -36,7 +36,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class SyntaxTree : AstNode { - public static readonly Role MemberRole = new Role("Member", null); [Slot("MemberRole")] public partial AstNodeCollection Members { get; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs index 5f346c6a6..a9951c010 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs @@ -24,7 +24,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class TupleAstType : AstType { - public static readonly Role ElementRole = new Role("Element", null); [Slot("ElementRole")] public partial AstNodeCollection Elements { get; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ConstructorDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ConstructorDeclaration.cs index 73f13c345..8a0065663 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ConstructorDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ConstructorDeclaration.cs @@ -36,7 +36,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class ConstructorDeclaration : EntityDeclaration { - public static readonly Role InitializerRole = new Role("Initializer", null); public override SymbolKind SymbolKind { get { return SymbolKind.Constructor; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs index b4bec4b16..9c3b89ed4 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs @@ -25,18 +25,16 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { public abstract class EntityDeclaration : AstNode { - public static readonly Role AttributeRole = new Role("Attribute", null); // Modifiers are stored in the Modifiers scalar; this role only tags the keyword tokens the // output visitor emits (e.g. for the override-link reference in TextTokenWriter). // 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 PrivateImplementationTypeRole = new Role("PrivateImplementationType", null); public abstract SymbolKind SymbolKind { get; } public virtual AstNodeCollection Attributes { - get { return base.GetChildrenByRole(AttributeRole); } + get { return base.GetChildrenByRole(SlotKind.Attribute); } } public Modifiers Modifiers { get; set; } @@ -48,21 +46,21 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public virtual string Name { get { - return GetChildByRole(Roles.Identifier)?.Name ?? string.Empty; + return GetChildByRole(SlotKind.Identifier)?.Name ?? string.Empty; } set { - SetChildByRole(Roles.Identifier, Identifier.Create(value, TextLocation.Empty)); + SetChildByRole(SlotKind.Identifier, Identifier.Create(value, TextLocation.Empty)); } } public virtual Identifier NameToken { - get { return GetChildByRole(Roles.Identifier); } - set { SetChildByRole(Roles.Identifier, value); } + get { return GetChildByRole(SlotKind.Identifier); } + set { SetChildByRole(SlotKind.Identifier, value); } } public virtual AstType ReturnType { - get { return GetChildByRole(Roles.Type); } - set { SetChildByRole(Roles.Type, value); } + get { return GetChildByRole(SlotKind.Type); } + set { SetChildByRole(SlotKind.Type, value); } } protected bool MatchAttributesAndModifiers(EntityDeclaration o, PatternMatching.Match match) diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EnumMemberDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EnumMemberDeclaration.cs index 9cc55205d..1105f6dac 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EnumMemberDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EnumMemberDeclaration.cs @@ -36,7 +36,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false)] public partial class EnumMemberDeclaration : EntityDeclaration { - public static readonly Role InitializerRole = new Role("Initializer", null); public override SymbolKind SymbolKind { get { return SymbolKind.Field; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EventDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EventDeclaration.cs index 669897752..da6d40812 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EventDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EventDeclaration.cs @@ -79,8 +79,6 @@ 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 AddAccessorRole = new Role("AddAccessor", null); - public static readonly Role RemoveAccessorRole = new Role("RemoveAccessor", null); public override SymbolKind SymbolKind { get { return SymbolKind.Event; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs index b089578c1..33610a3bc 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/FixedFieldDeclaration.cs @@ -34,7 +34,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class FixedFieldDeclaration : EntityDeclaration { public static readonly TokenRole FixedKeywordRole = new TokenRole("fixed"); - public static readonly Role VariableRole = new Role("FixedVariable", null); public override SymbolKind SymbolKind { get { return SymbolKind.Field; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/IndexerDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/IndexerDeclaration.cs index ce8031db2..ab1a6df99 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/IndexerDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/IndexerDeclaration.cs @@ -45,9 +45,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public partial class IndexerDeclaration : EntityDeclaration { public static readonly TokenRole ThisKeywordRole = new TokenRole("this"); - public static readonly Role GetterRole = PropertyDeclaration.GetterRole; - public static readonly Role SetterRole = PropertyDeclaration.SetterRole; - public static readonly Role ExpressionBodyRole = new Role("ExpressionBody", null); public override SymbolKind SymbolKind { get { return SymbolKind.Indexer; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/MethodDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/MethodDeclaration.cs index d9dfde343..2e5c34da0 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/MethodDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/MethodDeclaration.cs @@ -72,7 +72,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public bool IsExtensionMethod { get { - ParameterDeclaration pd = (ParameterDeclaration)GetChildByRole(Roles.Parameter); + ParameterDeclaration pd = (ParameterDeclaration)GetChildByRole(SlotKind.Parameter); return pd != null && pd.HasThisModifier; } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs index 667334828..dd75fe002 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs @@ -37,7 +37,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax [DecompilerAstNode(hasNullNode: false, hasPatternPlaceholder: true)] public partial class ParameterDeclaration : AstNode { - public static readonly Role AttributeRole = EntityDeclaration.AttributeRole; public static readonly TokenRole ThisModifierRole = new TokenRole("this"); public static readonly TokenRole ScopedRefRole = new TokenRole("scoped"); public static readonly TokenRole RefModifierRole = new TokenRole("ref"); diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs index dda4e2fdc..8a49f747c 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/PropertyDeclaration.cs @@ -44,9 +44,6 @@ 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 GetterRole = new Role("Getter", null); - public static readonly Role SetterRole = new Role("Setter", null); - public static readonly Role ExpressionBodyRole = new Role("ExpressionBody", null); public override SymbolKind SymbolKind { get { return SymbolKind.Property; } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index dbcb8ad86..7331e5526 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -633,11 +633,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax { if (ConvertUnboundTypeArguments && typeArguments[i].Kind == TypeKind.UnboundTypeArgument) { - result.AddChild(MakeSimpleType(typeParameters[i].Name), Roles.TypeArgument); + result.AddChild(MakeSimpleType(typeParameters[i].Name), SlotKind.TypeArgument); } else { - result.AddChild(ConvertType(typeArguments[i]), Roles.TypeArgument); + result.AddChild(ConvertType(typeArguments[i]), SlotKind.TypeArgument); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs b/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs index 96f6b9ce6..20ca149a1 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs @@ -393,7 +393,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { // We cannot use checked/unchecked for top-level-expressions. } - else if (expr.Role is Role || expr.Role is Role) + else if (expr.Slot?.ChildType is Type ct && ct.IsAssignableFrom(typeof(Expression))) { // We use '<' so that expressions are introduced on the deepest level possible (goal 3) var costIfWrapWithChecked = result.CostInCheckedContext.WrapInCheckedExpr(); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index fe154fc3f..511fa49de 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -725,14 +725,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } }, - BlockStatement.StatementRole); + SlotKind.Statement); } else { insertionParent.InsertChildBefore( v.InsertionPoint.nextNode, vds, - BlockStatement.StatementRole); + SlotKind.Statement); insertionParent.InsertChildBefore( v.InsertionPoint.nextNode, new ExpressionStatement { @@ -750,7 +750,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } }, - BlockStatement.StatementRole); + SlotKind.Statement); } } else @@ -758,7 +758,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms insertionParent.InsertChildBefore( v.InsertionPoint.nextNode, vds, - BlockStatement.StatementRole); + SlotKind.Statement); } } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs b/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs index 11d2de87b..6021d0254 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/FixNameCollisions.cs @@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms foreach (var typeDecl in rootNode.DescendantsAndSelf.OfType()) { var memberNames = typeDecl.Members.Select(m => { - var type = m.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole); + var type = m.GetChildByRole(SlotKind.PrivateImplementationType); return type is null ? m.Name : type + "." + m.Name; }).ToHashSet(); // memberNames does not include fields or non-custom events because those @@ -72,7 +72,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms ISymbol symbol = node.GetSymbol(); if (symbol != null && renamedSymbols.TryGetValue(symbol, out string? newName)) { - node.GetChildByRole(Roles.Identifier).Name = newName; + node.GetChildByRole(SlotKind.Identifier).Name = newName; } } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs index 06dbd1099..e4ee9dd7f 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs @@ -73,7 +73,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { resolvedNamespaces.Add(resolvedNamespace); } - rootNode.InsertChildAfter(insertionPoint, new UsingDeclaration { Import = nsType }, SyntaxTree.MemberRole); + rootNode.InsertChildAfter(insertionPoint, new UsingDeclaration { Import = nsType }, SlotKind.Member); } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs index 506fbbebb..fd4e72165 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs @@ -192,7 +192,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms if (next is ForStatement forStatement && ForStatementUsesVariable(forStatement, variable)) { node.Remove(); - next.InsertChildAfter(null, node, ForStatement.InitializerRole); + next.InsertChildAfter(null, node, SlotKind.Initializer); return (ForStatement)next; } Match m3 = forPattern.Match(next); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs b/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs index 1cf5192bc..a981df05c 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/TransformFieldAndConstructorInitializers.cs @@ -482,7 +482,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms var ci = new ConstructorInitializer { ConstructorInitializerType = type }; // Move arguments from invocation to initializer: - invocation.GetChildrenByRole(Roles.Argument).MoveTo(ci.Arguments); + invocation.GetChildrenByRole(SlotKind.Argument).MoveTo(ci.Arguments); // Add the initializer: (unless it is the default 'base()') if (!(ci.ConstructorInitializerType == ConstructorInitializerType.Base && ci.Arguments.Count == 0)) constructorDeclaration.Initializer = ci.CopyAnnotationsFrom(invocation); @@ -619,7 +619,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms foreach (var param in PrimaryConstructorDecl.Parameters) { param.Remove(); - this.TypeDeclaration.InsertChildAfter(insertionPoint, param, Roles.Parameter); + this.TypeDeclaration.InsertChildAfter(insertionPoint, param, SlotKind.Parameter); insertionPoint = param; } } diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 1d42c0d2b..0000d4bb7 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -264,7 +264,6 @@ - diff --git a/ICSharpCode.Decompiler/Output/TextTokenWriter.cs b/ICSharpCode.Decompiler/Output/TextTokenWriter.cs index f8cd2e1ef..2886d6b84 100644 --- a/ICSharpCode.Decompiler/Output/TextTokenWriter.cs +++ b/ICSharpCode.Decompiler/Output/TextTokenWriter.cs @@ -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) is null) + if (member != null && node.GetChildByRole(SlotKind.Identifier) is null) { switch (member) { diff --git a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs index fd7f401cc..04fb296eb 100644 --- a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs +++ b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs @@ -350,7 +350,7 @@ namespace ICSharpCode.ILSpy.Languages { if (identifier.Name == "value" && identifier.Ancestors.OfType().FirstOrDefault() is { } accessor - && accessor.Role != PropertyDeclaration.GetterRole) + && accessor.Slot?.Kind != SlotKind.Getter) { color = valueKeywordColor; } @@ -476,17 +476,17 @@ namespace ICSharpCode.ILSpy.Languages AstNode node = nodeStack.Peek(); var symbol = node.GetSymbol(); - if (symbol == null && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression) + if (symbol == null && node.Slot?.Kind == SlotKind.TargetExpression && node.Parent is InvocationExpression) { symbol = node.Parent.GetSymbol(); } - if (symbol != null && node.Role == Roles.Type && node.Parent is ObjectCreateExpression) + if (symbol != null && node.Slot?.Kind == SlotKind.Type && node.Parent is ObjectCreateExpression) { var ctorSymbol = node.Parent.GetSymbol(); if (ctorSymbol != null) symbol = ctorSymbol; } - if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) + if (node is IdentifierExpression && node.Slot?.Kind == SlotKind.TargetExpression && node.Parent is InvocationExpression && symbol is IMember member) { var declaringType = member.DeclaringType; if (declaringType != null && declaringType.Kind == TypeKind.Delegate)