mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
Add workaround for equal lambda parameter symbols with different hashcodes
This commit is contained in:
@@ -18,6 +18,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
private void VisitParameter(ParameterSyntax p)
|
||||
{
|
||||
var symbol = Context.GetModel(p).GetDeclaredSymbol(p)!;
|
||||
Context.CacheLambdaParameterSymbol(symbol, p);
|
||||
Parameter.Create(Context, symbol, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,11 +55,17 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public static Parameter Create(Context cx, IParameterSymbol param, IEntity parent, Parameter? original = null) =>
|
||||
ParameterFactory.Instance.CreateEntity(cx, param, (param, parent, original));
|
||||
public static Parameter Create(Context cx, IParameterSymbol param, IEntity parent, Parameter? original = null)
|
||||
{
|
||||
var cachedSymbol = cx.GetPossiblyCachedParameterSymbol(param);
|
||||
return ParameterFactory.Instance.CreateEntity(cx, cachedSymbol, (cachedSymbol, parent, original));
|
||||
}
|
||||
|
||||
public static Parameter Create(Context cx, IParameterSymbol param) =>
|
||||
ParameterFactory.Instance.CreateEntity(cx, param, (param, null, null));
|
||||
public static Parameter Create(Context cx, IParameterSymbol param)
|
||||
{
|
||||
var cachedSymbol = cx.GetPossiblyCachedParameterSymbol(param);
|
||||
return ParameterFactory.Instance.CreateEntity(cx, cachedSymbol, (cachedSymbol, null, null));
|
||||
}
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
|
||||
@@ -39,6 +39,36 @@ namespace Semmle.Extraction.CSharp
|
||||
private SemanticModel? cachedModelForTree;
|
||||
private SemanticModel? cachedModelForOtherTrees;
|
||||
|
||||
// The below is a workaround to the bug reported in https://github.com/dotnet/roslyn/issues/58226
|
||||
// Lambda parameters that are equal according to `SymbolEqualityComparer.Default`, might have different
|
||||
// hash-codes, and as a result might not be found in `symbolEntityCache` by hash-code lookup.
|
||||
internal IParameterSymbol GetPossiblyCachedParameterSymbol(IParameterSymbol param)
|
||||
{
|
||||
if ((param.ContainingSymbol as IMethodSymbol)?.MethodKind != MethodKind.AnonymousFunction)
|
||||
{
|
||||
return param;
|
||||
}
|
||||
|
||||
foreach (var sr in param.DeclaringSyntaxReferences)
|
||||
{
|
||||
var syntax = sr.GetSyntax();
|
||||
if (lambdaParameterCache.TryGetValue(syntax, out var cached) &&
|
||||
SymbolEqualityComparer.Default.Equals(param, cached))
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
internal void CacheLambdaParameterSymbol(IParameterSymbol param, SyntaxNode syntax)
|
||||
{
|
||||
lambdaParameterCache[syntax] = param;
|
||||
}
|
||||
|
||||
private readonly Dictionary<SyntaxNode, IParameterSymbol> lambdaParameterCache = new Dictionary<SyntaxNode, IParameterSymbol>();
|
||||
|
||||
/// <summary>
|
||||
/// The current compilation unit.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user