diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/IParameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/IParameter.cs
new file mode 100644
index 00000000000..d3f3a04c08f
--- /dev/null
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/IParameter.cs
@@ -0,0 +1,9 @@
+namespace Semmle.Extraction.CSharp.Entities
+{
+ ///
+ /// Marker interface for parameter entities.
+ ///
+ internal interface IParameter : IEntity
+ {
+ }
+}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs
index 49ef9a4a6e9..9cca0683f00 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs
@@ -7,16 +7,23 @@ using Semmle.Extraction.CSharp.Populators;
namespace Semmle.Extraction.CSharp.Entities
{
- internal class Parameter : CachedSymbol, IExpressionParentEntity
+ internal class Parameter : CachedSymbol, 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;
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Trap/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Trap/Tuples.cs
index b789eaa2e9c..c1d082bbee2 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Trap/Tuples.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Trap/Tuples.cs
@@ -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) =>