@@ -16,6 +16,7 @@ private void AnalyzeDependencies(Solution solution)
16
16
var loop = 0 ;
17
17
foreach ( var element in _codeGraph . Nodes . Values )
18
18
{
19
+ // TODO atr Analyze if we can have more than one symbol!
19
20
var symbol = _elementIdToSymbolMap [ element . Id ] ;
20
21
21
22
if ( symbol is IEventSymbol eventSymbol )
@@ -75,13 +76,13 @@ private void AnalyzeGlobalStatementsForAssembly(Solution solution)
75
76
}
76
77
77
78
// Find the existing assembly element
78
- var symbolKey = GetSymbolKey ( assemblySymbol ) ;
79
+ var symbolKey = assemblySymbol . Key ( ) ;
79
80
var assemblyElement = _symbolKeyToElementMap [ symbolKey ] ;
80
81
81
82
// Create a dummy class for this assembly's global statements
82
83
var dummyClassId = Guid . NewGuid ( ) . ToString ( ) ;
83
84
var dummyClassName = "GlobalStatements" ;
84
- var dummyClassFullName = BuildSymbolName ( assemblySymbol ) + "." + dummyClassName ;
85
+ var dummyClassFullName = assemblySymbol . BuildSymbolName ( ) + "." + dummyClassName ;
85
86
var dummyClass = new CodeElement ( dummyClassId , CodeElementType . Class , dummyClassName , dummyClassFullName ,
86
87
assemblyElement ) ;
87
88
_codeGraph . Nodes [ dummyClassId ] = dummyClass ;
@@ -108,6 +109,7 @@ private void AnalyzeGlobalStatementsForAssembly(Solution solution)
108
109
}
109
110
}
110
111
}
112
+
111
113
private void AnalyzeAttributeDependencies ( CodeElement element , ISymbol symbol )
112
114
{
113
115
foreach ( var attributeData in symbol . GetAttributes ( ) )
@@ -238,7 +240,7 @@ private void FindImplementations(CodeElement methodElement, IMethodSymbol method
238
240
var implementingMethod = implementingType . FindImplementationForInterfaceMember ( methodSymbol ) ;
239
241
if ( implementingMethod != null )
240
242
{
241
- var implementingElement = _symbolKeyToElementMap . GetValueOrDefault ( GetSymbolKey ( implementingMethod ) ) ;
243
+ var implementingElement = _symbolKeyToElementMap . GetValueOrDefault ( implementingMethod . Key ( ) ) ;
242
244
if ( implementingElement != null )
243
245
{
244
246
// Note: Implementations for external methods are not in our map
@@ -283,20 +285,10 @@ private bool IsTypeDerivedFrom(INamedTypeSymbol type, INamedTypeSymbol baseType)
283
285
private void AddMethodOverrideDependency ( CodeElement sourceElement , IMethodSymbol methodSymbol ,
284
286
List < SourceLocation > locations )
285
287
{
286
- if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( methodSymbol ) , out var targetElement ) )
287
- {
288
- AddDependency ( sourceElement , DependencyType . Overrides , targetElement , locations ) ;
289
- }
290
- else if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( methodSymbol . ContainingType ) ,
291
- out var containingTypeElement ) )
292
- {
293
- // Trace.WriteLine("Method override not captured. It is likely that the base method is generic or external code.");
294
-
295
- // If we don't have the method itself in our map, add a dependency to its containing type
296
- // Maybe we override a framework method. Happens also if the base method is a generic one.
297
- // In this case the GetSymbolKey is different. One uses T, the overriding method uses the actual type.
298
- AddDependency ( sourceElement , DependencyType . Overrides , containingTypeElement , locations ) ;
299
- }
288
+ // If we don't have the method itself in our map, add a dependency to its containing type
289
+ // Maybe we override a framework method. Happens also if the base method is a generic one.
290
+ // In this case the GetSymbolKey is different. One uses T, the overriding method uses the actual type.
291
+ AddDependencyWithFallbackToContainingType ( sourceElement , methodSymbol , DependencyType . Overrides , locations ) ;
300
292
}
301
293
302
294
private void AnalyzeFieldDependencies ( CodeElement fieldElement , IFieldSymbol fieldSymbol )
@@ -378,20 +370,13 @@ private void AnalyzeMethodBody(CodeElement sourceElement, SyntaxNode node, Seman
378
370
379
371
private void AddEventUsageDependency ( CodeElement sourceElement , IEventSymbol eventSymbol )
380
372
{
381
- if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( eventSymbol ) , out var eventElement ) )
382
- {
383
- AddDependency ( sourceElement , DependencyType . Uses , eventElement , [ ] ) ;
384
- }
385
- else if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( eventSymbol . ContainingType ) ,
386
- out var containingTypeElement ) )
387
- {
388
- // If we don't have the event itself in our map, add a dependency to its containing type
389
- AddDependency ( sourceElement , DependencyType . Uses , containingTypeElement , [ ] ) ;
390
- }
373
+ // If we don't have the event itself in our map, add a dependency to its containing type
374
+ AddDependencyWithFallbackToContainingType ( sourceElement , eventSymbol , DependencyType . Uses , [ ] ) ;
391
375
}
392
376
393
377
private void AddCallsDependency ( CodeElement sourceElement , IMethodSymbol methodSymbol , SourceLocation location )
394
378
{
379
+ //Debug.Assert(FindCodeElement(methodSymbol)!= null);
395
380
//Trace.WriteLine($"Adding call dependency: {sourceElement.Name} -> {methodSymbol.Name}");
396
381
397
382
if ( methodSymbol . IsExtensionMethod )
@@ -400,16 +385,13 @@ private void AddCallsDependency(CodeElement sourceElement, IMethodSymbol methodS
400
385
methodSymbol = methodSymbol . ReducedFrom ?? methodSymbol ;
401
386
}
402
387
403
- if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( methodSymbol ) , out var targetElement ) )
388
+ if ( methodSymbol . IsGenericMethod && FindCodeElement ( methodSymbol ) is null )
404
389
{
405
- AddDependency ( sourceElement , DependencyType . Calls , targetElement , [ location ] ) ;
390
+ methodSymbol = methodSymbol . OriginalDefinition ;
406
391
}
392
+
407
393
// If the method is not in our map, we might want to add a dependency to its containing type
408
- else if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( methodSymbol . ContainingType ) ,
409
- out var containingTypeElement ) )
410
- {
411
- AddDependency ( sourceElement , DependencyType . Calls , containingTypeElement , [ location ] ) ;
412
- }
394
+ AddDependencyWithFallbackToContainingType ( sourceElement , methodSymbol , DependencyType . Calls , [ location ] ) ;
413
395
}
414
396
415
397
@@ -442,38 +424,8 @@ private void AddTypeDependency(CodeElement sourceElement, ITypeSymbol typeSymbol
442
424
break ;
443
425
444
426
case INamedTypeSymbol namedTypeSymbol :
445
- var symbolKey = GetSymbolKey ( namedTypeSymbol ) ;
446
- if ( _symbolKeyToElementMap . TryGetValue ( symbolKey , out var targetElement ) )
447
- {
448
- // The type is internal (part of our codebase)
449
- AddDependency ( sourceElement , dependencyType , targetElement , location != null ? [ location ] : [ ] ) ;
450
-
451
- if ( namedTypeSymbol . IsGenericType )
452
- {
453
- // Add "Uses" dependencies to type arguments
454
- foreach ( var typeArg in namedTypeSymbol . TypeArguments )
455
- {
456
- AddTypeDependency ( sourceElement , typeArg , DependencyType . Uses , location ) ;
457
- }
458
- }
459
- }
460
- else
461
- {
462
- // The type is external
463
-
464
- // Optionally, you might want to track external dependencies
465
- // AddExternalDependency(sourceElement, namedTypeSymbol, dependencyType, location);
466
- if ( namedTypeSymbol . IsGenericType )
467
- {
468
- // For example List<MyType>
469
- // Add "Uses" dependencies to type arguments, which might be internal
470
- foreach ( var typeArg in namedTypeSymbol . TypeArguments )
471
- {
472
- AddTypeDependency ( sourceElement , typeArg , DependencyType . Uses , location ) ;
473
- }
474
- }
475
- }
476
427
428
+ AddNamedTypeDependency ( sourceElement , namedTypeSymbol , dependencyType , location ) ;
477
429
break ;
478
430
479
431
case IPointerTypeSymbol pointerTypeSymbol :
@@ -491,8 +443,8 @@ private void AddTypeDependency(CodeElement sourceElement, ITypeSymbol typeSymbol
491
443
break ;
492
444
default :
493
445
// Handle other type symbols (e.g., type parameters)
494
- symbolKey = GetSymbolKey ( typeSymbol ) ;
495
- if ( _symbolKeyToElementMap . TryGetValue ( symbolKey , out targetElement ) )
446
+ var symbolKey = typeSymbol . Key ( ) ;
447
+ if ( _symbolKeyToElementMap . TryGetValue ( symbolKey , out var targetElement ) )
496
448
{
497
449
AddDependency ( sourceElement , dependencyType , targetElement , location != null ? [ location ] : [ ] ) ;
498
450
}
@@ -501,6 +453,44 @@ private void AddTypeDependency(CodeElement sourceElement, ITypeSymbol typeSymbol
501
453
}
502
454
}
503
455
456
+ private void AddNamedTypeDependency ( CodeElement sourceElement , INamedTypeSymbol namedTypeSymbol ,
457
+ DependencyType dependencyType ,
458
+ SourceLocation ? location )
459
+ {
460
+ var targetElement = FindCodeElement ( namedTypeSymbol ) ;
461
+ if ( targetElement != null )
462
+ {
463
+ // The type is internal (part of our codebase)
464
+ AddDependency ( sourceElement , dependencyType , targetElement , location != null ? [ location ] : [ ] ) ;
465
+ }
466
+ else
467
+ {
468
+ // The type is external or a constructed generic type
469
+ // Note the constructed type is not in our CodeElement map!
470
+ // It is not found in phase1 the way we parse it but the original definition is.
471
+ var originalDefinition = namedTypeSymbol . OriginalDefinition ;
472
+ var originalSymbolKey = originalDefinition . Key ( ) ;
473
+
474
+ if ( _symbolKeyToElementMap . TryGetValue ( originalSymbolKey , out var originalTargetElement ) )
475
+ {
476
+ // We found the original definition, add dependency to it
477
+ AddDependency ( sourceElement , dependencyType , originalTargetElement , location != null ? [ location ] : [ ] ) ;
478
+ }
479
+ // The type is truly external, you might want to log this or handle it differently
480
+ // AddExternalDependency(sourceElement, namedTypeSymbol, dependencyType, location);
481
+ }
482
+
483
+ if ( namedTypeSymbol . IsGenericType )
484
+ {
485
+ // Add "Uses" dependencies to type arguments
486
+ foreach ( var typeArg in namedTypeSymbol . TypeArguments )
487
+ {
488
+ AddTypeDependency ( sourceElement , typeArg , DependencyType . Uses , location ) ;
489
+ }
490
+ }
491
+ }
492
+
493
+
504
494
private void AnalyzeIdentifier ( CodeElement sourceElement , IdentifierNameSyntax identifierSyntax ,
505
495
SemanticModel semanticModel )
506
496
{
@@ -517,7 +507,7 @@ private void AnalyzeIdentifier(CodeElement sourceElement, IdentifierNameSyntax i
517
507
518
508
if ( symbolInfo . Symbol is IFieldSymbol fieldSymbol )
519
509
{
520
- AddFieldDependency ( sourceElement , fieldSymbol , DependencyType . Uses ) ;
510
+ AddDependencyWithFallbackToContainingType ( sourceElement , fieldSymbol , DependencyType . Uses ) ;
521
511
}
522
512
}
523
513
@@ -533,7 +523,7 @@ private void AnalyzeMemberAccess(CodeElement sourceElement, MemberAccessExpressi
533
523
}
534
524
else if ( symbolInfo . Symbol is IFieldSymbol fieldSymbol )
535
525
{
536
- AddFieldDependency ( sourceElement , fieldSymbol , DependencyType . Uses ) ;
526
+ AddDependencyWithFallbackToContainingType ( sourceElement , fieldSymbol , DependencyType . Uses ) ;
537
527
}
538
528
}
539
529
@@ -543,27 +533,40 @@ private void AnalyzeMemberAccess(CodeElement sourceElement, MemberAccessExpressi
543
533
private void AddPropertyCallDependency ( CodeElement sourceElement , IPropertySymbol propertySymbol ,
544
534
List < SourceLocation > locations )
545
535
{
546
- if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( propertySymbol ) , out var targetElement ) )
536
+ AddDependencyWithFallbackToContainingType ( sourceElement , propertySymbol , DependencyType . Calls , locations ) ;
537
+ }
538
+
539
+ private void AddDependencyWithFallbackToContainingType ( CodeElement sourceElement , ISymbol symbol ,
540
+ DependencyType dependencyType , List < SourceLocation > ? locations = null )
541
+ {
542
+ // If we don't have the property itself in our map, add a dependency to its containing type
543
+ if ( locations == null )
544
+ {
545
+ locations = [ ] ;
546
+ }
547
+
548
+ var targetElement = FindCodeElement ( symbol ) ;
549
+ if ( targetElement != null )
547
550
{
548
- AddDependency ( sourceElement , DependencyType . Calls , targetElement , locations ) ;
551
+ AddDependency ( sourceElement , dependencyType , targetElement , locations ) ;
552
+ return ;
549
553
}
550
- else if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( propertySymbol . ContainingType ) ,
551
- out var containingTypeElement ) )
554
+
555
+ var containingTypeElement = FindCodeElement ( symbol . ContainingType ) ;
556
+ if ( containingTypeElement != null )
552
557
{
553
- AddDependency ( sourceElement , DependencyType . Calls , containingTypeElement , locations ) ;
558
+ AddDependency ( sourceElement , dependencyType , containingTypeElement , locations ) ;
554
559
}
555
560
}
556
561
557
- private void AddFieldDependency ( CodeElement sourceElement , IFieldSymbol fieldSymbol , DependencyType dependencyType )
562
+ private CodeElement ? FindCodeElement ( ISymbol ? symbol )
558
563
{
559
- if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( fieldSymbol ) , out var targetElement ) )
564
+ if ( symbol is null )
560
565
{
561
- AddDependency ( sourceElement , dependencyType , targetElement , [ ] ) ;
562
- }
563
- else if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( fieldSymbol . ContainingType ) ,
564
- out var containingTypeElement ) )
565
- {
566
- AddDependency ( sourceElement , dependencyType , containingTypeElement , [ ] ) ;
566
+ return null ;
567
567
}
568
+
569
+ _symbolKeyToElementMap . TryGetValue ( symbol . Key ( ) , out var element ) ;
570
+ return element ;
568
571
}
569
572
}
0 commit comments