Merge pull request #4413 from hvitved/csharp/indexer-explicit-interface

C#: Fix extraction of library indexers with explicit interface implementations
This commit is contained in:
Tom Hvitved
2020-10-07 18:49:30 +02:00
committed by GitHub
4 changed files with 29 additions and 17 deletions

View File

@@ -9,25 +9,28 @@ namespace Semmle.Extraction.CSharp.Entities
protected Accessor(Context cx, IMethodSymbol init)
: base(cx, init) { }
/// <summary>
/// Gets the property symbol associated accessor `symbol`, or `null`
/// if there is no associated symbol.
/// </summary>
public static IPropertySymbol GetPropertySymbol(IMethodSymbol symbol)
{
// Usually, the property/indexer can be fetched from the associated symbol
var prop = symbol.AssociatedSymbol as IPropertySymbol;
if (prop != null)
return prop;
// But for properties/indexers that implement explicit interfaces, Roslyn
// does not properly populate `AssociatedSymbol`
var props = symbol.ContainingType.GetMembers().OfType<IPropertySymbol>();
props = props.Where(p => SymbolEqualityComparer.Default.Equals(symbol, p.GetMethod) || SymbolEqualityComparer.Default.Equals(symbol, p.SetMethod));
return props.SingleOrDefault();
}
/// <summary>
/// Gets the property symbol associated with this accessor.
/// </summary>
IPropertySymbol PropertySymbol
{
get
{
// Usually, the property/indexer can be fetched from the associated symbol
var prop = symbol.AssociatedSymbol as IPropertySymbol;
if (prop != null)
return prop;
// But for properties/indexers that implement explicit interfaces, Roslyn
// does not properly populate `AssociatedSymbol`
var props = symbol.ContainingType.GetMembers().OfType<IPropertySymbol>();
props = props.Where(p => SymbolEqualityComparer.Default.Equals(symbol, p.GetMethod) || SymbolEqualityComparer.Default.Equals(symbol, p.SetMethod));
return props.SingleOrDefault();
}
}
IPropertySymbol PropertySymbol => GetPropertySymbol(symbol);
public new Accessor OriginalDefinition => Create(Context, symbol.OriginalDefinition);

View File

@@ -240,7 +240,7 @@ namespace Semmle.Extraction.CSharp.Entities
return Destructor.Create(cx, methodDecl);
case MethodKind.PropertyGet:
case MethodKind.PropertySet:
return methodDecl.AssociatedSymbol is null ? OrdinaryMethod.Create(cx, methodDecl) : (Method)Accessor.Create(cx, methodDecl);
return Accessor.GetPropertySymbol(methodDecl) is null ? OrdinaryMethod.Create(cx, methodDecl) : (Method)Accessor.Create(cx, methodDecl);
case MethodKind.EventAdd:
case MethodKind.EventRemove:
return EventAccessor.Create(cx, methodDecl);