Skip to content

Commit bfd4318

Browse files
committed
C#: Synthesize the implicit extension parameters for generics.
1 parent a8eccea commit bfd4318

File tree

2 files changed

+25
-17
lines changed

2 files changed

+25
-17
lines changed

csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,28 @@ internal abstract class Method : CachedSymbol<IMethodSymbol>, IExpressionParentE
1414
protected Method(Context cx, IMethodSymbol init)
1515
: base(cx, init) { }
1616

17-
protected void PopulateParameters()
18-
{
19-
var positionOffset = 0;
20-
var originalMethod = OriginalDefinition;
17+
private IParameter? SyntheticParameter { get; set; }
2118

19+
private int SynthesizeExtensionParameter()
20+
{
2221
// Synthesize implicit parameter for extension methods declared using extension(...) syntax.
2322
if (Symbol.ContainingSymbol is INamedTypeSymbol type &&
24-
type.IsExtension && !string.IsNullOrEmpty(type.ExtensionParameter?.Name) &&
25-
!Symbol.IsStatic &&
26-
Symbol.AssociatedExtensionImplementation is not null)
23+
type.IsExtension && type.ExtensionParameter is IParameterSymbol parameter &&
24+
!string.IsNullOrEmpty(parameter.Name) && !Symbol.IsStatic)
2725
{
28-
// TODO: Check that this works for generics as well. We might need to also take
29-
ImplicitExtensionParameter.Create(Context, this);
30-
positionOffset++;
26+
var originalSyntheticParam = OriginalDefinition.SyntheticParameter;
27+
SyntheticParameter = ImplicitExtensionParameter.Create(Context, this, parameter, originalSyntheticParam);
28+
return 1;
3129
}
3230

31+
return 0;
32+
}
33+
34+
protected void PopulateParameters()
35+
{
36+
var originalMethod = OriginalDefinition;
37+
var positionOffset = SynthesizeExtensionParameter();
38+
3339
IEnumerable<IParameterSymbol> parameters = Symbol.Parameters;
3440
IEnumerable<IParameterSymbol> originalParameters = originalMethod.Symbol.Parameters;
3541

csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -271,11 +271,13 @@ internal class ImplicitExtensionParameter : FreshEntity, IParameter
271271
{
272272
private Method ExtensionMethod { get; }
273273
private IParameterSymbol ExtensionParameter { get; }
274+
private IParameter Original { get; }
274275

275-
private ImplicitExtensionParameter(Context cx, Method method) : base(cx)
276+
private ImplicitExtensionParameter(Context cx, Method method, IParameterSymbol parameter, IParameter? original) : base(cx)
276277
{
277278
ExtensionMethod = method;
278-
ExtensionParameter = method.Symbol.AssociatedExtensionImplementation!.Parameters[0];
279+
ExtensionParameter = parameter;
280+
Original = original ?? this;
279281
}
280282

281283
private static int Ordinal => 0;
@@ -326,7 +328,7 @@ protected override void Populate(TextWriter trapFile)
326328
PopulateRefKind(trapFile, ExtensionParameter.RefKind);
327329

328330
var type = Type.Create(Context, ExtensionParameter.Type);
329-
trapFile.@params(this, Name, type.TypeRef, Ordinal, ParamKind, ExtensionMethod, this);
331+
trapFile.@params(this, Name, type.TypeRef, Ordinal, ParamKind, ExtensionMethod, Original);
330332

331333
if (Context.OnlyScaffold)
332334
{
@@ -356,11 +358,11 @@ protected override void Populate(TextWriter trapFile)
356358
}
357359
}
358360

359-
public static ImplicitExtensionParameter Create(Context cx, Method method)
361+
public static ImplicitExtensionParameter Create(Context cx, Method method, IParameterSymbol parameter, IParameter? original)
360362
{
361-
var parameter = new ImplicitExtensionParameter(cx, method);
362-
parameter.TryPopulate();
363-
return parameter;
363+
var p = new ImplicitExtensionParameter(cx, method, parameter, original);
364+
p.TryPopulate();
365+
return p;
364366
}
365367
}
366368

0 commit comments

Comments
 (0)