mirror of
https://github.com/github/codeql.git
synced 2025-12-17 17:23:36 +01:00
89 lines
2.9 KiB
C#
89 lines
2.9 KiB
C#
using Microsoft.CodeAnalysis;
|
|
using System.Linq;
|
|
|
|
namespace Semmle.Extraction.CSharp.Entities
|
|
{
|
|
class Accessor : Method
|
|
{
|
|
protected Accessor(Context cx, IMethodSymbol init)
|
|
: base(cx, init) { }
|
|
|
|
/// <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 => symbol.Equals(p.GetMethod) || symbol.Equals(p.SetMethod));
|
|
return props.SingleOrDefault();
|
|
}
|
|
}
|
|
|
|
public new Accessor OriginalDefinition => Create(Context, symbol.OriginalDefinition);
|
|
|
|
public override void Populate()
|
|
{
|
|
PopulateMethod();
|
|
ExtractModifiers();
|
|
ContainingType.ExtractGenerics();
|
|
|
|
var prop = PropertySymbol;
|
|
if (prop == null)
|
|
{
|
|
Context.ModelError(symbol, "Unhandled accessor associated symbol");
|
|
return;
|
|
}
|
|
|
|
var parent = Property.Create(Context, prop);
|
|
int kind;
|
|
Accessor unboundAccessor;
|
|
if (symbol.Equals(prop.GetMethod))
|
|
{
|
|
kind = 1;
|
|
unboundAccessor = Create(Context, prop.OriginalDefinition.GetMethod);
|
|
}
|
|
else if (symbol.Equals(prop.SetMethod))
|
|
{
|
|
kind = 2;
|
|
unboundAccessor = Create(Context, prop.OriginalDefinition.SetMethod);
|
|
}
|
|
else
|
|
{
|
|
Context.ModelError(symbol, "Unhandled accessor kind");
|
|
return;
|
|
}
|
|
|
|
Context.Emit(Tuples.accessors(this, kind, symbol.Name, parent, unboundAccessor));
|
|
|
|
foreach (var l in Locations)
|
|
Context.Emit(Tuples.accessor_location(this, l));
|
|
|
|
Overrides();
|
|
|
|
if (symbol.FromSource() && Block == null)
|
|
{
|
|
Context.Emit(Tuples.compiler_generated(this));
|
|
}
|
|
}
|
|
|
|
public new static Accessor Create(Context cx, IMethodSymbol symbol) =>
|
|
AccessorFactory.Instance.CreateEntity(cx, symbol);
|
|
|
|
class AccessorFactory : ICachedEntityFactory<IMethodSymbol, Accessor>
|
|
{
|
|
public static readonly AccessorFactory Instance = new AccessorFactory();
|
|
|
|
public Accessor Create(Context cx, IMethodSymbol init) => new Accessor(cx, init);
|
|
}
|
|
}
|
|
}
|