Browse Source

Store member modifiers and composed-type specifiers as scalar fields

Member and local modifiers were stored as modifier token children, and a
ComposedType's ref/readonly/nullable/pointer specifiers and an array rank as
token and comma children. The output visitor already derived all of these
from scalar accessors, so move them to plain enum/bool/int fields. This
removes another dependency on token children ahead of deleting the token
nodes; the emitted keyword and specifier sequences are unchanged.
Assisted-by: Claude:claude-opus-4-8:Claude Code
pull/3807/head
Siegfried Pammer 3 weeks ago committed by Siegfried Pammer
parent
commit
fbfc93bb41
  1. 47
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  2. 69
      ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs
  3. 5
      ICSharpCode.Decompiler/CSharp/Syntax/Statements/VariableDeclarationStatement.cs
  4. 51
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/EntityDeclaration.cs

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

@ -489,12 +489,15 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -489,12 +489,15 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
}
protected virtual void WriteModifiers(IEnumerable<CSharpModifierToken> modifierTokens)
protected virtual void WriteModifiers(Modifiers modifiers)
{
foreach (CSharpModifierToken modifier in modifierTokens)
foreach (Modifiers modifier in CSharpModifierToken.AllModifiers)
{
modifier.AcceptVisitor(this);
Space();
if ((modifiers & modifier) == modifier)
{
WriteKeyword(CSharpModifierToken.GetModifierName(modifier), EntityDeclaration.ModifierRole);
Space();
}
}
}
@ -1556,7 +1559,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1556,7 +1559,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(delegateDeclaration);
WriteAttributes(delegateDeclaration.Attributes);
WriteModifiers(delegateDeclaration.ModifierTokens);
WriteModifiers(delegateDeclaration.Modifiers);
WriteKeyword(Roles.DelegateKeyword);
delegateDeclaration.ReturnType.AcceptVisitor(this);
Space();
@ -1604,7 +1607,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -1604,7 +1607,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(typeDeclaration);
WriteAttributes(typeDeclaration.Attributes);
WriteModifiers(typeDeclaration.ModifierTokens);
WriteModifiers(typeDeclaration.Modifiers);
BraceStyle braceStyle;
switch (typeDeclaration.ClassType)
{
@ -2250,7 +2253,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2250,7 +2253,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
public virtual void VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
{
StartNode(variableDeclarationStatement);
WriteModifiers(variableDeclarationStatement.GetChildrenByRole(VariableDeclarationStatement.ModifierRole));
WriteModifiers(variableDeclarationStatement.Modifiers);
variableDeclarationStatement.Type.AcceptVisitor(this);
Space();
WriteCommaSeparatedList(variableDeclarationStatement.Variables);
@ -2306,7 +2309,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2306,7 +2309,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(accessor);
WriteAttributes(accessor.Attributes);
WriteModifiers(accessor.ModifierTokens);
WriteModifiers(accessor.Modifiers);
BraceStyle style = policy.StatementBraceStyle;
if (accessor.Role == PropertyDeclaration.GetterRole)
{
@ -2343,7 +2346,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2343,7 +2346,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(constructorDeclaration);
WriteAttributes(constructorDeclaration.Attributes);
WriteModifiers(constructorDeclaration.ModifierTokens);
WriteModifiers(constructorDeclaration.Modifiers);
TypeDeclaration type = constructorDeclaration.Parent as TypeDeclaration;
if (type != null && type.Name != constructorDeclaration.Name)
WriteIdentifier((Identifier)type.NameToken.Clone());
@ -2384,8 +2387,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2384,8 +2387,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(destructorDeclaration);
WriteAttributes(destructorDeclaration.Attributes);
WriteModifiers(destructorDeclaration.ModifierTokens);
if (destructorDeclaration.ModifierTokens.Any())
WriteModifiers(destructorDeclaration.Modifiers);
if (destructorDeclaration.Modifiers != Modifiers.None)
{
Space();
}
@ -2406,7 +2409,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2406,7 +2409,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(enumMemberDeclaration);
WriteAttributes(enumMemberDeclaration.Attributes);
WriteModifiers(enumMemberDeclaration.ModifierTokens);
WriteModifiers(enumMemberDeclaration.Modifiers);
WriteIdentifier(enumMemberDeclaration.NameToken);
if (!enumMemberDeclaration.Initializer.IsNull)
{
@ -2422,7 +2425,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2422,7 +2425,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(extensionDeclaration);
WriteAttributes(extensionDeclaration.Attributes);
WriteModifiers(extensionDeclaration.ModifierTokens);
WriteModifiers(extensionDeclaration.Modifiers);
WriteKeyword(ExtensionDeclaration.ExtensionKeywordRole);
WriteTypeParameters(extensionDeclaration.TypeParameters);
Space(policy.SpaceBeforeMethodDeclarationParentheses);
@ -2452,7 +2455,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2452,7 +2455,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(eventDeclaration);
WriteAttributes(eventDeclaration.Attributes);
WriteModifiers(eventDeclaration.ModifierTokens);
WriteModifiers(eventDeclaration.Modifiers);
WriteKeyword(EventDeclaration.EventKeywordRole);
eventDeclaration.ReturnType.AcceptVisitor(this);
Space();
@ -2465,7 +2468,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2465,7 +2468,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(customEventDeclaration);
WriteAttributes(customEventDeclaration.Attributes);
WriteModifiers(customEventDeclaration.ModifierTokens);
WriteModifiers(customEventDeclaration.Modifiers);
WriteKeyword(CustomEventDeclaration.EventKeywordRole);
customEventDeclaration.ReturnType.AcceptVisitor(this);
Space();
@ -2489,7 +2492,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2489,7 +2492,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(fieldDeclaration);
WriteAttributes(fieldDeclaration.Attributes);
WriteModifiers(fieldDeclaration.ModifierTokens);
WriteModifiers(fieldDeclaration.Modifiers);
fieldDeclaration.ReturnType.AcceptVisitor(this);
Space();
WriteCommaSeparatedList(fieldDeclaration.Variables);
@ -2501,7 +2504,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2501,7 +2504,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(fixedFieldDeclaration);
WriteAttributes(fixedFieldDeclaration.Attributes);
WriteModifiers(fixedFieldDeclaration.ModifierTokens);
WriteModifiers(fixedFieldDeclaration.Modifiers);
WriteKeyword(FixedFieldDeclaration.FixedKeywordRole);
Space();
fixedFieldDeclaration.ReturnType.AcceptVisitor(this);
@ -2530,7 +2533,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2530,7 +2533,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(indexerDeclaration);
WriteAttributes(indexerDeclaration.Attributes);
WriteModifiers(indexerDeclaration.ModifierTokens);
WriteModifiers(indexerDeclaration.Modifiers);
indexerDeclaration.ReturnType.AcceptVisitor(this);
Space();
WritePrivateImplementationType(indexerDeclaration.PrivateImplementationType);
@ -2575,7 +2578,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2575,7 +2578,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(methodDeclaration);
WriteAttributes(methodDeclaration.Attributes);
WriteModifiers(methodDeclaration.ModifierTokens);
WriteModifiers(methodDeclaration.Modifiers);
methodDeclaration.ReturnType.AcceptVisitor(this);
Space();
WritePrivateImplementationType(methodDeclaration.PrivateImplementationType);
@ -2595,7 +2598,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2595,7 +2598,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(operatorDeclaration);
WriteAttributes(operatorDeclaration.Attributes);
WriteModifiers(operatorDeclaration.ModifierTokens);
WriteModifiers(operatorDeclaration.Modifiers);
if (operatorDeclaration.OperatorType == OperatorType.Explicit || operatorDeclaration.OperatorType == OperatorType.CheckedExplicit)
{
WriteKeyword(OperatorDeclaration.ExplicitRole);
@ -2695,7 +2698,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2695,7 +2698,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(propertyDeclaration);
WriteAttributes(propertyDeclaration.Attributes);
WriteModifiers(propertyDeclaration.ModifierTokens);
WriteModifiers(propertyDeclaration.Modifiers);
propertyDeclaration.ReturnType.AcceptVisitor(this);
Space();
WritePrivateImplementationType(propertyDeclaration.PrivateImplementationType);
@ -2901,7 +2904,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2901,7 +2904,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StartNode(arraySpecifier);
WriteToken(Roles.LBracket);
foreach (var comma in arraySpecifier.GetChildrenByRole(Roles.Comma))
for (int i = 0; i < arraySpecifier.Dimensions - 1; i++)
{
writer.WriteToken(Roles.Comma, ",");
}

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

@ -50,40 +50,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -50,40 +50,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// This is used for C# 7 ref locals/ref return.
/// Parameters use ParameterDeclaration.ParameterModifier instead.
/// </summary>
public bool HasRefSpecifier {
get {
return !GetChildByRole(RefRole).IsNull;
}
set {
SetChildByRole(RefRole, value ? new CSharpTokenNode(TextLocation.Empty, null) : null);
}
}
public bool HasRefSpecifier { get; set; }
/// <summary>
/// Gets/sets whether this type has a 'readonly' specifier.
/// This is used for C# 7.2 'ref readonly' locals/ref return.
/// Parameters use ParameterDeclaration.ParameterModifier instead.
/// </summary>
public bool HasReadOnlySpecifier {
get {
return !GetChildByRole(ReadonlyRole).IsNull;
}
set {
SetChildByRole(ReadonlyRole, value ? new CSharpTokenNode(TextLocation.Empty, null) : null);
}
}
public bool HasReadOnlySpecifier { get; set; }
[Slot("Roles.Type")]
public partial AstType BaseType { get; set; }
public bool HasNullableSpecifier {
get {
return !GetChildByRole(NullableRole).IsNull;
}
set {
SetChildByRole(NullableRole, value ? new CSharpTokenNode(TextLocation.Empty, null) : null);
}
}
public bool HasNullableSpecifier { get; set; }
public bool HasOnlyNullableSpecifier {
get {
@ -91,39 +70,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -91,39 +70,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
public CSharpTokenNode NullableSpecifierToken {
get {
return GetChildByRole(NullableRole);
}
}
int pointerRank;
public int PointerRank {
get {
return GetChildrenByRole(PointerRole).Count;
return pointerRank;
}
set {
if (value < 0)
throw new ArgumentOutOfRangeException();
int d = this.PointerRank;
while (d > value)
{
GetChildByRole(PointerRole).Remove();
d--;
}
while (d < value)
{
InsertChildBefore(GetChildByRole(PointerRole), new CSharpTokenNode(TextLocation.Empty, PointerRole), PointerRole);
d++;
}
throw new ArgumentOutOfRangeException(nameof(value));
pointerRank = value;
}
}
[Slot("ArraySpecifierRole")]
public partial AstNodeCollection<ArraySpecifier> ArraySpecifiers { get; }
[Slot("PointerRole")]
public partial AstNodeCollection<CSharpTokenNode> PointerTokens { get; }
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
ComposedType o = other as ComposedType;
@ -207,22 +169,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -207,22 +169,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
get { return GetChildByRole(Roles.LBracket); }
}
public int Dimensions {
get { return 1 + GetChildrenByRole(Roles.Comma).Count; }
set {
int d = this.Dimensions;
while (d > value)
{
GetChildByRole(Roles.Comma).Remove();
d--;
}
while (d < value)
{
InsertChildBefore(GetChildByRole(Roles.Comma), new CSharpTokenNode(TextLocation.Empty, Roles.Comma), Roles.Comma);
d++;
}
}
}
public int Dimensions { get; set; } = 1;
public CSharpTokenNode RBracketToken {
get { return GetChildByRole(Roles.RBracket); }

5
ICSharpCode.Decompiler/CSharp/Syntax/Statements/VariableDeclarationStatement.cs

@ -41,10 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -41,10 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
this.Variables.Add(new VariableInitializer(name, initializer));
}
public Modifiers Modifiers {
get { return EntityDeclaration.GetModifiers(this); }
set { EntityDeclaration.SetModifiers(this, value); }
}
public Modifiers Modifiers { get; set; }
[Slot("Roles.Type")]
public partial AstType Type { get; set; }

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

@ -39,20 +39,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -39,20 +39,13 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
get { return base.GetChildrenByRole(AttributeRole); }
}
public Modifiers Modifiers {
get { return GetModifiers(this); }
set { SetModifiers(this, value); }
}
public Modifiers Modifiers { get; set; }
public bool HasModifier(Modifiers mod)
{
return (Modifiers & mod) == mod;
}
public IEnumerable<CSharpModifierToken> ModifierTokens {
get { return GetChildrenByRole(ModifierRole); }
}
public virtual string Name {
get {
return GetChildByRole(Roles.Identifier).Name;
@ -76,48 +69,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -76,48 +69,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
get { return GetChildByRole(Roles.Semicolon); }
}
internal static Modifiers GetModifiers(AstNode node)
{
Modifiers m = 0;
foreach (CSharpModifierToken t in node.GetChildrenByRole(ModifierRole))
{
m |= t.Modifier;
}
return m;
}
internal static void SetModifiers(AstNode node, Modifiers newValue)
{
Modifiers oldValue = GetModifiers(node);
AstNode insertionPos = node.GetChildrenByRole(AttributeRole).LastOrDefault();
foreach (Modifiers m in CSharpModifierToken.AllModifiers)
{
if ((m & newValue) != 0)
{
if ((m & oldValue) == 0)
{
// Modifier was added
var newToken = new CSharpModifierToken(TextLocation.Empty, m);
node.InsertChildAfter(insertionPos, newToken, ModifierRole);
insertionPos = newToken;
}
else
{
// Modifier already exists
insertionPos = node.GetChildrenByRole(ModifierRole).First(t => t.Modifier == m);
}
}
else
{
if ((m & oldValue) != 0)
{
// Modifier was removed
node.GetChildrenByRole(ModifierRole).First(t => t.Modifier == m).Remove();
}
}
}
}
protected bool MatchAttributesAndModifiers(EntityDeclaration o, PatternMatching.Match match)
{
return (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) && this.Attributes.DoMatch(o.Attributes, match);

Loading…
Cancel
Save