Browse Source

Drop dead IFreezable/Freeze apparatus from the C# AST

The C# AST inherited NRefactory's freezable model (IFreezable, Freeze,
IsFrozen, a frozen flag bit, and ThrowIfFrozen guards on every mutator),
but the decompiler never uses it: nothing calls Freeze(), not even the
generated null-node singletons, so every IsFrozen guard only ever
evaluated false. The decompiler is single-threaded and never shares or
freezes nodes. Remove the whole apparatus as preparation for the
slot-based AST rewrite, which has no place for it. Roles are untouched
here, so the flags word keeps its role index; only the freed frozen bit
goes away.
pull/3807/head
Siegfried Pammer 2 weeks ago committed by Siegfried Pammer
parent
commit
1f738677c6
  1. 48
      ICSharpCode.Decompiler/CSharp/Syntax/AstNode.cs
  2. 1
      ICSharpCode.Decompiler/CSharp/Syntax/CSharpModifierToken.cs
  3. 3
      ICSharpCode.Decompiler/CSharp/Syntax/DocumentationReference.cs
  4. 4
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AnonymousMethodExpression.cs
  5. 2
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/LambdaExpression.cs
  6. 1
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NullReferenceExpression.cs
  7. 3
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PrimitiveExpression.cs
  8. 8
      ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Comment.cs
  9. 1
      ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeDeclaration.cs
  10. 2
      ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeParameterDeclaration.cs
  11. 3
      ICSharpCode.Decompiler/CSharp/Syntax/Identifier.cs
  12. 1
      ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs
  13. 2
      ICSharpCode.Decompiler/CSharp/Syntax/PrimitiveType.cs
  14. 1
      ICSharpCode.Decompiler/CSharp/Syntax/SyntaxTree.cs
  15. 1
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs
  16. 4
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/ParameterDeclaration.cs

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

@ -37,7 +37,7 @@ using ICSharpCode.Decompiler.TypeSystem; @@ -37,7 +37,7 @@ using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public abstract class AstNode : AbstractAnnotatable, IFreezable, INode, ICloneable
public abstract partial class AstNode : AbstractAnnotatable, INode, ICloneable
{
// the Root role must be available when creating the null nodes, so we can't put it in the Roles class
internal static readonly Role<AstNode?> RootRole = new Role<AstNode?>("Root", null);
@ -135,40 +135,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -135,40 +135,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
// Flags, from least significant to most significant bits:
// - Role.RoleIndexBits: role index
// - 1 bit: IsFrozen
protected uint flags = RootRole.Index;
// Derived classes may also use a few bits,
// for example Identifier uses 1 bit for IsVerbatim
const uint roleIndexMask = (1u << Role.RoleIndexBits) - 1;
const uint frozenBit = 1u << Role.RoleIndexBits;
protected const int AstNodeFlagsUsedBits = Role.RoleIndexBits + 1;
protected AstNode()
{
if (IsNull)
Freeze();
}
public bool IsFrozen {
get { return (flags & frozenBit) != 0; }
}
public void Freeze()
{
if (!IsFrozen)
{
for (AstNode? child = firstChild; child != null; child = child.nextSibling)
child.Freeze();
flags |= frozenBit;
}
}
protected void ThrowIfFrozen()
{
if (IsFrozen)
throw new InvalidOperationException("Cannot mutate frozen " + GetType().Name);
}
protected const int AstNodeFlagsUsedBits = Role.RoleIndexBits;
public abstract NodeType NodeType {
get;
@ -211,7 +183,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -211,7 +183,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
throw new ArgumentNullException(nameof(value));
if (!value.IsValid(this))
throw new ArgumentException("This node is not valid in the new role.");
ThrowIfFrozen();
SetRole(value);
}
}
@ -382,13 +353,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -382,13 +353,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
throw new ArgumentNullException(nameof(role));
if (child == null || child.IsNull)
return;
ThrowIfFrozen();
if (child == this)
throw new ArgumentException("Cannot add a node to itself as a child.", nameof(child));
if (child.parent != null)
throw new ArgumentException("Node is already used in another tree.", nameof(child));
if (child.IsFrozen)
throw new ArgumentException("Cannot add a frozen node.", nameof(child));
AddChildUnsafe(child, role);
}
@ -396,13 +364,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -396,13 +364,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
if (child == null || child.IsNull)
return;
ThrowIfFrozen();
if (child == this)
throw new ArgumentException("Cannot add a node to itself as a child.", nameof(child));
if (child.parent != null)
throw new ArgumentException("Node is already used in another tree.", nameof(child));
if (child.IsFrozen)
throw new ArgumentException("Cannot add a frozen node.", nameof(child));
AddChildUnsafe(child, child.Role);
}
@ -437,11 +402,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -437,11 +402,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
if (child == null || child.IsNull)
return;
ThrowIfFrozen();
if (child.parent != null)
throw new ArgumentException("Node is already used in another tree.", nameof(child));
if (child.IsFrozen)
throw new ArgumentException("Cannot add a frozen node.", nameof(child));
if (nextSibling.parent != this)
throw new ArgumentException("NextSibling is not a child of this node.", nameof(nextSibling));
// No need to test for "Cannot add children to null nodes",
@ -481,7 +443,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -481,7 +443,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
if (parent != null)
{
ThrowIfFrozen();
if (prevSibling != null)
{
Debug.Assert(prevSibling.nextSibling == this);
@ -524,7 +485,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -524,7 +485,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node");
}
ThrowIfFrozen();
// Because this method doesn't statically check the new node's type with the role,
// we perform a runtime test:
if (!this.Role.IsValid(newNode))
@ -545,9 +505,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -545,9 +505,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
throw new ArgumentException("Node is already used in another tree.", nameof(newNode));
}
}
if (newNode.IsFrozen)
throw new ArgumentException("Cannot add a frozen node.", nameof(newNode));
newNode.parent = parent;
newNode.SetRole(this.Role);
newNode.prevSibling = prevSibling;
@ -623,7 +580,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -623,7 +580,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
copy.lastChild = null;
copy.prevSibling = null;
copy.nextSibling = null;
copy.flags &= ~frozenBit; // unfreeze the copy
// Then perform a deep copy:
for (AstNode? cur = firstChild; cur != null; cur = cur.nextSibling)

1
ICSharpCode.Decompiler/CSharp/Syntax/CSharpModifierToken.cs

@ -38,7 +38,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -38,7 +38,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public Modifiers Modifier {
get { return modifier; }
set {
ThrowIfFrozen();
this.modifier = value;
}
}

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

@ -43,7 +43,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -43,7 +43,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public SymbolKind SymbolKind {
get { return symbolKind; }
set {
ThrowIfFrozen();
symbolKind = value;
}
}
@ -55,7 +54,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -55,7 +54,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public OperatorType OperatorType {
get { return operatorType; }
set {
ThrowIfFrozen();
operatorType = value;
}
}
@ -66,7 +64,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -66,7 +64,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool HasParameterList {
get { return hasParameterList; }
set {
ThrowIfFrozen();
hasParameterList = value;
}
}

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

@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool IsAsync {
get { return isAsync; }
set { ThrowIfFrozen(); isAsync = value; }
set { isAsync = value; }
}
// used to tell the difference between delegate {} and delegate () {}
@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool HasParameterList {
get { return hasParameterList || Parameters.Any(); }
set { ThrowIfFrozen(); hasParameterList = value; }
set { hasParameterList = value; }
}
public CSharpTokenNode DelegateToken {

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

@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool IsAsync {
get { return isAsync; }
set { ThrowIfFrozen(); isAsync = value; }
set { isAsync = value; }
}
public CSharpTokenNode LParToken {

1
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/NullReferenceExpression.cs

@ -40,7 +40,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -40,7 +40,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
internal void SetStartLocation(TextLocation value)
{
ThrowIfFrozen();
this.location = value;
}

3
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/PrimitiveExpression.cs

@ -57,7 +57,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -57,7 +57,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
internal void SetLocation(TextLocation startLocation, TextLocation endLocation)
{
ThrowIfFrozen();
this.startLocation = startLocation;
this.endLocation = endLocation;
}
@ -68,7 +67,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -68,7 +67,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public object Value {
get { return this.value; }
set {
ThrowIfFrozen();
this.value = value;
}
}
@ -76,7 +74,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -76,7 +74,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public LiteralFormat Format {
get { return format; }
set {
ThrowIfFrozen();
format = value;
}
}

8
ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/Comment.cs

@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -62,7 +62,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public CommentType CommentType {
get { return commentType; }
set { ThrowIfFrozen(); commentType = value; }
set { commentType = value; }
}
/// <summary>
@ -78,14 +78,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -78,14 +78,14 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool StartsLine {
get { return startsLine; }
set { ThrowIfFrozen(); startsLine = value; }
set { startsLine = value; }
}
string content;
public string Content {
get { return content; }
set { ThrowIfFrozen(); content = value; }
set { content = value; }
}
TextLocation startLocation;
@ -104,13 +104,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -104,13 +104,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
internal void SetStartLocation(TextLocation value)
{
ThrowIfFrozen();
this.startLocation = value;
}
internal void SetEndLocation(TextLocation value)
{
ThrowIfFrozen();
this.endLocation = value;
}

1
ICSharpCode.Decompiler/CSharp/Syntax/GeneralScope/TypeDeclaration.cs

@ -83,7 +83,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -83,7 +83,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public ClassType ClassType {
get { return classType; }
set {
ThrowIfFrozen();
classType = value;
}
}

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

@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -45,7 +45,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public VarianceModifier Variance {
get { return variance; }
set { ThrowIfFrozen(); variance = value; }
set { variance = value; }
}
public CSharpTokenNode VarianceToken {

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

@ -72,7 +72,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -72,7 +72,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
set {
if (value == null)
throw new ArgumentNullException(nameof(value));
ThrowIfFrozen();
this.name = value;
}
}
@ -86,7 +85,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -86,7 +85,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
internal void SetStartLocation(TextLocation value)
{
ThrowIfFrozen();
this.startLocation = value;
}
@ -97,7 +95,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -97,7 +95,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return (flags & verbatimBit) != 0;
}
set {
ThrowIfFrozen();
if (value)
flags |= verbatimBit;
else

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

@ -37,7 +37,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -37,7 +37,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool IsDoubleColon {
get { return isDoubleColon; }
set {
ThrowIfFrozen();
isDoubleColon = value;
}
}

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

@ -41,7 +41,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -41,7 +41,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
set {
if (value == null)
throw new ArgumentNullException();
ThrowIfFrozen();
keyword = value;
}
}
@ -73,7 +72,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -73,7 +72,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
internal void SetStartLocation(TextLocation value)
{
ThrowIfFrozen();
this.location = value;
}

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

@ -49,7 +49,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -49,7 +49,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public string FileName {
get { return fileName; }
set {
ThrowIfFrozen();
fileName = value;
}
}

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

@ -173,7 +173,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -173,7 +173,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public OperatorType OperatorType {
get { return operatorType; }
set {
ThrowIfFrozen();
operatorType = value;
}
}

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

@ -110,7 +110,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -110,7 +110,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool HasThisModifier {
get { return hasThisModifier; }
set {
ThrowIfFrozen();
hasThisModifier = value;
}
}
@ -118,7 +117,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -118,7 +117,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool IsParams {
get { return isParams; }
set {
ThrowIfFrozen();
isParams = value;
}
}
@ -126,7 +124,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -126,7 +124,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public bool IsScopedRef {
get { return isScopedRef; }
set {
ThrowIfFrozen();
isScopedRef = value;
}
}
@ -136,7 +133,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -136,7 +133,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public ReferenceKind ParameterModifier {
get { return parameterModifier; }
set {
ThrowIfFrozen();
parameterModifier = value;
}
}

Loading…
Cancel
Save