Skip to content

Commit bf96e68

Browse files
committed
Fix review findings
1 parent c1d8091 commit bf96e68

File tree

1 file changed

+25
-38
lines changed
  • csharp/extractor/Semmle.Extraction.CSharp/Entities/Types

1 file changed

+25
-38
lines changed

csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Linq;
66
using Microsoft.CodeAnalysis;
77
using Microsoft.CodeAnalysis.CSharp.Syntax;
8+
using Semmle.Util;
89

910
namespace Semmle.Extraction.CSharp.Entities
1011
{
@@ -362,7 +363,7 @@ public override bool Equals(object? obj)
362363
/// Details can be found in https://www.ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf Chapter II.9.2 Generics and recursive inheritance graphs
363364
/// The dotnet runtime already implements this check as a runtime validation: https://github.com/dotnet/runtime/blob/e48e88d0fe9c2e494c0e6fd0c7c1fb54e7ddbdb1/src/coreclr/vm/generics.cpp#L748
364365
/// </summary>
365-
public class GenericsRecursionGraph
366+
private class GenericsRecursionGraph
366367
{
367368
private static readonly ConcurrentDictionary<INamedTypeSymbol, bool> resultCache = new(SymbolEqualityComparer.Default);
368369

@@ -377,15 +378,7 @@ public static bool HasExpandingCycle(ITypeSymbol start)
377378
return false;
378379
}
379380

380-
if (resultCache.TryGetValue(namedTypeDefinition, out var result))
381-
{
382-
return result;
383-
}
384-
385-
result = new GenericsRecursionGraph(namedTypeDefinition).HasExpandingCycle();
386-
resultCache.TryAdd(namedTypeDefinition, result);
387-
388-
return result;
381+
return resultCache.GetOrAdd(namedTypeDefinition, nt => new GenericsRecursionGraph(nt).HasExpandingCycle());
389382
}
390383

391384
private readonly INamedTypeSymbol startSymbol;
@@ -417,47 +410,42 @@ private void ComputeGraphEdges()
417410
if (reference.TypeArguments[i] is ITypeParameterSymbol source)
418411
{
419412
// non-expanding
420-
if (!edges.TryGetValue(source, out var targets))
421-
{
422-
targets = new List<(ITypeParameterSymbol, bool)>();
423-
edges.Add(source, targets);
424-
}
425-
targets.Add((target, false));
413+
edges.AddAnother(source, (target, false));
426414
}
427415
else if (reference.TypeArguments[i] is INamedTypeSymbol namedType)
428416
{
429417
// expanding
430418
var sources = GetAllNestedTypeParameters(namedType);
431419
foreach (var s in sources)
432420
{
433-
if (!edges.TryGetValue(s, out var targets))
434-
{
435-
targets = new List<(ITypeParameterSymbol, bool)>();
436-
edges.Add(s, targets);
437-
}
438-
targets.Add((target, true));
421+
edges.AddAnother(s, (target, true));
439422
}
440423
}
441424
}
442425
}
443426
}
444427

445-
private List<ITypeParameterSymbol> GetAllNestedTypeParameters(INamedTypeSymbol symbol)
428+
private static List<ITypeParameterSymbol> GetAllNestedTypeParameters(INamedTypeSymbol symbol)
446429
{
447430
var res = new List<ITypeParameterSymbol>();
448431

449-
foreach (var typeArgument in symbol.TypeArguments)
432+
void AddTypeParameters(INamedTypeSymbol symbol)
450433
{
451-
if (typeArgument is ITypeParameterSymbol typeParameter)
434+
foreach (var typeArgument in symbol.TypeArguments)
452435
{
453-
res.Add(typeParameter);
454-
}
455-
else if (typeArgument is INamedTypeSymbol namedType)
456-
{
457-
res.AddRange(GetAllNestedTypeParameters(namedType));
436+
if (typeArgument is ITypeParameterSymbol typeParameter)
437+
{
438+
res.Add(typeParameter);
439+
}
440+
else if (typeArgument is INamedTypeSymbol namedType)
441+
{
442+
AddTypeParameters(namedType);
443+
}
458444
}
459445
}
460446

447+
AddTypeParameters(symbol);
448+
461449
return res;
462450
}
463451

@@ -510,8 +498,8 @@ private bool HasExpandingCycle()
510498
private bool HasExpandingCycle(ITypeParameterSymbol start)
511499
{
512500
var visited = new HashSet<ITypeParameterSymbol>(SymbolEqualityComparer.Default);
513-
var recStack = new HashSet<ITypeParameterSymbol>(SymbolEqualityComparer.Default);
514-
var hasExpandingCycle = HasExpandingCycle(start, visited, recStack, start, hasSeenExpandingEdge: false);
501+
var path = new List<ITypeParameterSymbol>();
502+
var hasExpandingCycle = HasExpandingCycle(start, visited, path, hasSeenExpandingEdge: false);
515503
return hasExpandingCycle;
516504
}
517505

@@ -527,13 +515,12 @@ private bool HasExpandingCycle(ITypeParameterSymbol start)
527515
/// </summary>
528516
/// <param name="current">The current node that is being visited</param>
529517
/// <param name="visited">The nodes that have already been visited by any path.</param>
530-
/// <param name="currentPath">The nodes already visited on the current path. Could be a List<> if the order was important.</param>
531-
/// <param name="start">The start and end of the cycle. We're not looking for any cycle, but a cycle that goes back to the start.</param>
518+
/// <param name="currentPath">The nodes already visited on the current path.</param>
532519
/// <param name="hasSeenExpandingEdge">Whether an expanding edge was already seen in this path. We're looking for a cycle that has at least one expanding edge.</param>
533520
/// <returns></returns>
534-
private bool HasExpandingCycle(ITypeParameterSymbol current, HashSet<ITypeParameterSymbol> visited, HashSet<ITypeParameterSymbol> currentPath, ITypeParameterSymbol start, bool hasSeenExpandingEdge)
521+
private bool HasExpandingCycle(ITypeParameterSymbol current, HashSet<ITypeParameterSymbol> visited, List<ITypeParameterSymbol> currentPath, bool hasSeenExpandingEdge)
535522
{
536-
if (currentPath.Count > 0 && SymbolEqualityComparer.Default.Equals(current, start))
523+
if (currentPath.Count > 0 && SymbolEqualityComparer.Default.Equals(current, currentPath[0]))
537524
{
538525
return hasSeenExpandingEdge;
539526
}
@@ -550,13 +537,13 @@ private bool HasExpandingCycle(ITypeParameterSymbol current, HashSet<ITypeParame
550537

551538
foreach (var outgoingEdge in outgoingEdges)
552539
{
553-
if (HasExpandingCycle(outgoingEdge.To, visited, currentPath, start, hasSeenExpandingEdge: hasSeenExpandingEdge || outgoingEdge.IsExpanding))
540+
if (HasExpandingCycle(outgoingEdge.To, visited, currentPath, hasSeenExpandingEdge: hasSeenExpandingEdge || outgoingEdge.IsExpanding))
554541
{
555542
return true;
556543
}
557544
}
558545

559-
currentPath.Remove(current);
546+
currentPath.RemoveAt(currentPath.Count - 1);
560547
return false;
561548
}
562549
}

0 commit comments

Comments
 (0)