C#: Add parameter marker interface, allow a type to a parent for parameter and make it possible to specify a parameter position offset.

This commit is contained in:
Michael Nebel
2026-02-04 13:19:29 +01:00
parent dca10f8740
commit c68cd58f70
3 changed files with 31 additions and 10 deletions

View File

@@ -0,0 +1,9 @@
namespace Semmle.Extraction.CSharp.Entities
{
/// <summary>
/// Marker interface for parameter entities.
/// </summary>
internal interface IParameter : IEntity
{
}
}

View File

@@ -7,16 +7,23 @@ using Semmle.Extraction.CSharp.Populators;
namespace Semmle.Extraction.CSharp.Entities
{
internal class Parameter : CachedSymbol<IParameterSymbol>, IExpressionParentEntity
internal class Parameter : CachedSymbol<IParameterSymbol>, IExpressionParentEntity, IParameter
{
protected IEntity? Parent { get; set; }
protected Parameter Original { get; }
private int PositionOffset { get; set; }
protected Parameter(Context cx, IParameterSymbol init, IEntity? parent, Parameter? original)
private Parameter(Context cx, IParameterSymbol init, IEntity? parent, Parameter? original, int positionOffset)
: base(cx, init)
{
Parent = parent;
Original = original ?? this;
PositionOffset = positionOffset;
}
protected Parameter(Context cx, IParameterSymbol init, IEntity? parent, Parameter? original)
: this(cx, init, parent, original, 0)
{
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => Symbol.GetSymbolLocation();
@@ -32,7 +39,7 @@ namespace Semmle.Extraction.CSharp.Entities
RefReadOnly = 6
}
protected virtual int Ordinal => Symbol.Ordinal;
protected virtual int Ordinal => Symbol.Ordinal + PositionOffset;
private Kind ParamKind
{
@@ -55,23 +62,25 @@ namespace Semmle.Extraction.CSharp.Entities
if (Ordinal == 0)
{
if (Symbol.ContainingSymbol is IMethodSymbol method && method.IsExtensionMethod)
{
return Kind.This;
}
}
return Kind.None;
}
}
}
public static Parameter Create(Context cx, IParameterSymbol param, IEntity parent, Parameter? original = null)
public static Parameter Create(Context cx, IParameterSymbol param, IEntity parent, Parameter? original = null, int positionOffset = 0)
{
var cachedSymbol = cx.GetPossiblyCachedParameterSymbol(param);
return ParameterFactory.Instance.CreateEntity(cx, cachedSymbol, (cachedSymbol, parent, original));
return ParameterFactory.Instance.CreateEntity(cx, cachedSymbol, (cachedSymbol, parent, original, positionOffset));
}
public static Parameter Create(Context cx, IParameterSymbol param)
{
var cachedSymbol = cx.GetPossiblyCachedParameterSymbol(param);
return ParameterFactory.Instance.CreateEntity(cx, cachedSymbol, (cachedSymbol, null, null));
return ParameterFactory.Instance.CreateEntity(cx, cachedSymbol, (cachedSymbol, null, null, 0));
}
public override void WriteId(EscapingTextWriter trapFile)
@@ -79,6 +88,9 @@ namespace Semmle.Extraction.CSharp.Entities
if (Parent is null)
Parent = Method.Create(Context, Symbol.ContainingSymbol as IMethodSymbol);
if (Parent is null && Symbol.ContainingSymbol is INamedTypeSymbol type && type.IsExtension)
Parent = Type.Create(Context, type);
if (Parent is null)
throw new InternalError(Symbol, "Couldn't get parent of symbol.");
@@ -194,11 +206,11 @@ namespace Semmle.Extraction.CSharp.Entities
return syntax?.Default;
}
private class ParameterFactory : CachedEntityFactory<(IParameterSymbol, IEntity?, Parameter?), Parameter>
private class ParameterFactory : CachedEntityFactory<(IParameterSymbol, IEntity?, Parameter?, int), Parameter>
{
public static ParameterFactory Instance { get; } = new ParameterFactory();
public override Parameter Create(Context cx, (IParameterSymbol, IEntity?, Parameter?) init) => new Parameter(cx, init.Item1, init.Item2, init.Item3);
public override Parameter Create(Context cx, (IParameterSymbol, IEntity?, Parameter?, int) init) => new Parameter(cx, init.Item1, init.Item2, init.Item3, init.Item4);
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel;

View File

@@ -292,10 +292,10 @@ namespace Semmle.Extraction.CSharp
internal static void overrides(this TextWriter trapFile, Method overriding, Method overridden) =>
trapFile.WriteTuple("overrides", overriding, overridden);
internal static void param_location(this TextWriter trapFile, Parameter param, Location location) =>
internal static void param_location(this TextWriter trapFile, IParameter param, Location location) =>
trapFile.WriteTuple("param_location", param, location);
internal static void @params(this TextWriter trapFile, Parameter param, string name, Type type, int child, Parameter.Kind mode, IEntity method, Parameter originalDefinition) =>
internal static void @params(this TextWriter trapFile, IParameter param, string name, Type type, int child, Parameter.Kind mode, IEntity method, IParameter originalDefinition) =>
trapFile.WriteTuple("params", param, name, type, child, (int)mode, method, originalDefinition);
internal static void parent_namespace(this TextWriter trapFile, IEntity type, Namespace parent) =>