|
5 | 5 | using System.Linq; |
6 | 6 | using Microsoft.CodeAnalysis; |
7 | 7 | using Semmle.Extraction.CSharp.Entities; |
| 8 | +using Semmle.Extraction.CSharp.Entities.Statements; |
8 | 9 |
|
9 | 10 | namespace Semmle.Extraction.CSharp |
10 | 11 | { |
@@ -631,8 +632,30 @@ public static bool IsSourceDeclaration(this IParameterSymbol parameter) |
631 | 632 | /// Return true if this method is a compiler-generated extension method. |
632 | 633 | /// </summary> |
633 | 634 | public static bool IsCompilerGeneratedExtensionMethod(this IMethodSymbol method) => |
634 | | - method.IsImplicitlyDeclared && method.IsExtensionMethod; |
| 635 | + method.TryGetExtensionMethod(out _); |
635 | 636 |
|
| 637 | + /// <summary> |
| 638 | + /// Returns true if this method is a compiler-generated extension method, |
| 639 | + /// and outputs the original extension method declaration. |
| 640 | + /// </summary> |
| 641 | + public static bool TryGetExtensionMethod(this IMethodSymbol method, out IMethodSymbol? declaration) |
| 642 | + { |
| 643 | + declaration = null; |
| 644 | + if (method.IsImplicitlyDeclared && method.ContainingSymbol is INamedTypeSymbol containingType) |
| 645 | + { |
| 646 | + // Extension types are declared within the same type as the generated |
| 647 | + // extension method implementation. |
| 648 | + var extensions = containingType.GetMembers() |
| 649 | + .OfType<INamedTypeSymbol>() |
| 650 | + .Where(t => t.IsExtension); |
| 651 | + // Find the original extension method that maps to this implementation (if any). |
| 652 | + declaration = extensions.SelectMany(e => e.GetMembers()) |
| 653 | + .OfType<IMethodSymbol>() |
| 654 | + .FirstOrDefault(m => SymbolEqualityComparer.Default.Equals(m.AssociatedExtensionImplementation, method)); |
| 655 | + return declaration is not null; |
| 656 | + } |
| 657 | + return false; |
| 658 | + } |
636 | 659 | /// <summary> |
637 | 660 | /// Gets the base type of `symbol`. Unlike `symbol.BaseType`, this excludes effective base |
638 | 661 | /// types of type parameters as well as `object` base types. |
|
0 commit comments