@@ -16,6 +16,7 @@ private void AnalyzeDependencies(Solution solution)
1616 var loop = 0 ;
1717 foreach ( var element in _codeGraph . Nodes . Values )
1818 {
19+ // TODO atr Analyze if we can have more than one symbol!
1920 var symbol = _elementIdToSymbolMap [ element . Id ] ;
2021
2122 if ( symbol is IEventSymbol eventSymbol )
@@ -75,13 +76,13 @@ private void AnalyzeGlobalStatementsForAssembly(Solution solution)
7576 }
7677
7778 // Find the existing assembly element
78- var symbolKey = GetSymbolKey ( assemblySymbol ) ;
79+ var symbolKey = assemblySymbol . Key ( ) ;
7980 var assemblyElement = _symbolKeyToElementMap [ symbolKey ] ;
8081
8182 // Create a dummy class for this assembly's global statements
8283 var dummyClassId = Guid . NewGuid ( ) . ToString ( ) ;
8384 var dummyClassName = "GlobalStatements" ;
84- var dummyClassFullName = BuildSymbolName ( assemblySymbol ) + "." + dummyClassName ;
85+ var dummyClassFullName = assemblySymbol . BuildSymbolName ( ) + "." + dummyClassName ;
8586 var dummyClass = new CodeElement ( dummyClassId , CodeElementType . Class , dummyClassName , dummyClassFullName ,
8687 assemblyElement ) ;
8788 _codeGraph . Nodes [ dummyClassId ] = dummyClass ;
@@ -108,6 +109,7 @@ private void AnalyzeGlobalStatementsForAssembly(Solution solution)
108109 }
109110 }
110111 }
112+
111113 private void AnalyzeAttributeDependencies ( CodeElement element , ISymbol symbol )
112114 {
113115 foreach ( var attributeData in symbol . GetAttributes ( ) )
@@ -238,7 +240,7 @@ private void FindImplementations(CodeElement methodElement, IMethodSymbol method
238240 var implementingMethod = implementingType . FindImplementationForInterfaceMember ( methodSymbol ) ;
239241 if ( implementingMethod != null )
240242 {
241- var implementingElement = _symbolKeyToElementMap . GetValueOrDefault ( GetSymbolKey ( implementingMethod ) ) ;
243+ var implementingElement = _symbolKeyToElementMap . GetValueOrDefault ( implementingMethod . Key ( ) ) ;
242244 if ( implementingElement != null )
243245 {
244246 // Note: Implementations for external methods are not in our map
@@ -283,20 +285,10 @@ private bool IsTypeDerivedFrom(INamedTypeSymbol type, INamedTypeSymbol baseType)
283285 private void AddMethodOverrideDependency ( CodeElement sourceElement , IMethodSymbol methodSymbol ,
284286 List < SourceLocation > locations )
285287 {
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 ) ;
300292 }
301293
302294 private void AnalyzeFieldDependencies ( CodeElement fieldElement , IFieldSymbol fieldSymbol )
@@ -378,20 +370,13 @@ private void AnalyzeMethodBody(CodeElement sourceElement, SyntaxNode node, Seman
378370
379371 private void AddEventUsageDependency ( CodeElement sourceElement , IEventSymbol eventSymbol )
380372 {
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 , [ ] ) ;
391375 }
392376
393377 private void AddCallsDependency ( CodeElement sourceElement , IMethodSymbol methodSymbol , SourceLocation location )
394378 {
379+ //Debug.Assert(FindCodeElement(methodSymbol)!= null);
395380 //Trace.WriteLine($"Adding call dependency: {sourceElement.Name} -> {methodSymbol.Name}");
396381
397382 if ( methodSymbol . IsExtensionMethod )
@@ -400,16 +385,13 @@ private void AddCallsDependency(CodeElement sourceElement, IMethodSymbol methodS
400385 methodSymbol = methodSymbol . ReducedFrom ?? methodSymbol ;
401386 }
402387
403- if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( methodSymbol ) , out var targetElement ) )
388+ if ( methodSymbol . IsGenericMethod && FindCodeElement ( methodSymbol ) is null )
404389 {
405- AddDependency ( sourceElement , DependencyType . Calls , targetElement , [ location ] ) ;
390+ methodSymbol = methodSymbol . OriginalDefinition ;
406391 }
392+
407393 // 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 ] ) ;
413395 }
414396
415397
@@ -442,38 +424,8 @@ private void AddTypeDependency(CodeElement sourceElement, ITypeSymbol typeSymbol
442424 break ;
443425
444426 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- }
476427
428+ AddNamedTypeDependency ( sourceElement , namedTypeSymbol , dependencyType , location ) ;
477429 break ;
478430
479431 case IPointerTypeSymbol pointerTypeSymbol :
@@ -491,8 +443,8 @@ private void AddTypeDependency(CodeElement sourceElement, ITypeSymbol typeSymbol
491443 break ;
492444 default :
493445 // 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 ) )
496448 {
497449 AddDependency ( sourceElement , dependencyType , targetElement , location != null ? [ location ] : [ ] ) ;
498450 }
@@ -501,6 +453,44 @@ private void AddTypeDependency(CodeElement sourceElement, ITypeSymbol typeSymbol
501453 }
502454 }
503455
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+
504494 private void AnalyzeIdentifier ( CodeElement sourceElement , IdentifierNameSyntax identifierSyntax ,
505495 SemanticModel semanticModel )
506496 {
@@ -517,7 +507,7 @@ private void AnalyzeIdentifier(CodeElement sourceElement, IdentifierNameSyntax i
517507
518508 if ( symbolInfo . Symbol is IFieldSymbol fieldSymbol )
519509 {
520- AddFieldDependency ( sourceElement , fieldSymbol , DependencyType . Uses ) ;
510+ AddDependencyWithFallbackToContainingType ( sourceElement , fieldSymbol , DependencyType . Uses ) ;
521511 }
522512 }
523513
@@ -533,7 +523,7 @@ private void AnalyzeMemberAccess(CodeElement sourceElement, MemberAccessExpressi
533523 }
534524 else if ( symbolInfo . Symbol is IFieldSymbol fieldSymbol )
535525 {
536- AddFieldDependency ( sourceElement , fieldSymbol , DependencyType . Uses ) ;
526+ AddDependencyWithFallbackToContainingType ( sourceElement , fieldSymbol , DependencyType . Uses ) ;
537527 }
538528 }
539529
@@ -543,27 +533,40 @@ private void AnalyzeMemberAccess(CodeElement sourceElement, MemberAccessExpressi
543533 private void AddPropertyCallDependency ( CodeElement sourceElement , IPropertySymbol propertySymbol ,
544534 List < SourceLocation > locations )
545535 {
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 )
547550 {
548- AddDependency ( sourceElement , DependencyType . Calls , targetElement , locations ) ;
551+ AddDependency ( sourceElement , dependencyType , targetElement , locations ) ;
552+ return ;
549553 }
550- else if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( propertySymbol . ContainingType ) ,
551- out var containingTypeElement ) )
554+
555+ var containingTypeElement = FindCodeElement ( symbol . ContainingType ) ;
556+ if ( containingTypeElement != null )
552557 {
553- AddDependency ( sourceElement , DependencyType . Calls , containingTypeElement , locations ) ;
558+ AddDependency ( sourceElement , dependencyType , containingTypeElement , locations ) ;
554559 }
555560 }
556561
557- private void AddFieldDependency ( CodeElement sourceElement , IFieldSymbol fieldSymbol , DependencyType dependencyType )
562+ private CodeElement ? FindCodeElement ( ISymbol ? symbol )
558563 {
559- if ( _symbolKeyToElementMap . TryGetValue ( GetSymbolKey ( fieldSymbol ) , out var targetElement ) )
564+ if ( symbol is null )
560565 {
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 ;
567567 }
568+
569+ _symbolKeyToElementMap . TryGetValue ( symbol . Key ( ) , out var element ) ;
570+ return element ;
568571 }
569572}
0 commit comments