Browse Source

Fix #2413: Avoid global state in `TokenRole`.

We can already compactly store a `TokenRole` via the index+lookup in the `Role` base class.
The lookup in the base class is thread-safe; the one removed here was not.
pull/2418/head
Daniel Grunwald 4 years ago
parent
commit
108c5f643e
  1. 17
      ICSharpCode.Decompiler/CSharp/Syntax/CSharpTokenNode.cs
  2. 43
      ICSharpCode.Decompiler/CSharp/Syntax/TokenRole.cs

17
ICSharpCode.Decompiler/CSharp/Syntax/CSharpTokenNode.cs

@ -85,7 +85,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
int TokenLength { int TokenLength {
get { get {
return TokenRole.TokenLengths[(int)(this.flags >> AstNodeFlagsUsedBits)]; uint tokenRoleIndex = (this.flags >> AstNodeFlagsUsedBits);
if (Role.GetByIndex(tokenRoleIndex) is TokenRole r)
{
return r.Length;
}
return 0;
} }
} }
@ -99,12 +104,17 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
this.startLocation = location; this.startLocation = location;
if (role != null) if (role != null)
this.flags |= role.TokenIndex << AstNodeFlagsUsedBits; this.flags |= role.Index << AstNodeFlagsUsedBits;
} }
public override string ToString(CSharpFormattingOptions formattingOptions) public override string ToString(CSharpFormattingOptions formattingOptions)
{ {
return TokenRole.Tokens[(int)(this.flags >> AstNodeFlagsUsedBits)]; uint tokenRoleIndex = (this.flags >> AstNodeFlagsUsedBits);
if (Role.GetByIndex(tokenRoleIndex) is TokenRole r)
{
return r.Token;
}
return string.Empty;
} }
public override void AcceptVisitor(IAstVisitor visitor) public override void AcceptVisitor(IAstVisitor visitor)
@ -129,4 +139,3 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
} }
} }

43
ICSharpCode.Decompiler/CSharp/Syntax/TokenRole.cs

@ -1,5 +1,3 @@
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.CSharp.Syntax namespace ICSharpCode.Decompiler.CSharp.Syntax
{ {
/// <summary> /// <summary>
@ -7,57 +5,20 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
/// </summary> /// </summary>
public sealed class TokenRole : Role<CSharpTokenNode> public sealed class TokenRole : Role<CSharpTokenNode>
{ {
internal readonly static List<string> Tokens = new List<string>();
internal readonly static List<int> TokenLengths = new List<int>();
internal readonly uint TokenIndex;
static TokenRole()
{
// null token
Tokens.Add("");
TokenLengths.Add(0);
}
/// <summary> /// <summary>
/// Gets the token as string. Note that the token Name and Token value may differ. /// Gets the token as string. Note that the token Name and Token value may differ.
/// </summary> /// </summary>
public string Token { public string Token { get; }
get;
private set;
}
/// <summary> /// <summary>
/// Gets the char length of the token. /// Gets the char length of the token.
/// </summary> /// </summary>
public int Length { public int Length { get; }
get;
private set;
}
public TokenRole(string token) : base(token, CSharpTokenNode.Null) public TokenRole(string token) : base(token, CSharpTokenNode.Null)
{ {
this.Token = token; this.Token = token;
this.Length = token.Length; this.Length = token.Length;
bool found = false;
for (int i = 0; i < Tokens.Count; i++)
{
var existingToken = Tokens[i];
if (existingToken == token)
{
TokenIndex = (uint)i;
found = true;
break;
}
}
if (!found)
{
TokenIndex = (uint)Tokens.Count;
Tokens.Add(token);
TokenLengths.Add(this.Length);
}
} }
} }
} }

Loading…
Cancel
Save