Skip to content

Commit 4d9e078

Browse files
committed
C#: Add extractor support for object initializer methods.
1 parent 7c18195 commit 4d9e078

File tree

5 files changed

+93
-4
lines changed

5 files changed

+93
-4
lines changed

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ protected override void ExtractInitializers(TextWriter trapFile)
7474
{
7575
case SyntaxKind.BaseConstructorInitializer:
7676
initializerType = Symbol.ContainingType.BaseType!;
77+
ExtractObjectInitCall(trapFile);
7778
break;
7879
case SyntaxKind.ThisConstructorInitializer:
7980
initializerType = Symbol.ContainingType;
@@ -90,10 +91,12 @@ protected override void ExtractInitializers(TextWriter trapFile)
9091
var primaryInfo = Context.GetSymbolInfo(primaryInitializer);
9192
var primarySymbol = primaryInfo.Symbol;
9293

94+
ExtractObjectInitCall(trapFile);
9395
ExtractSourceInitializer(trapFile, primarySymbol?.ContainingType, (IMethodSymbol?)primarySymbol, primaryInitializer.ArgumentList, primaryInitializer.GetLocation());
9496
}
9597
else if (Symbol.MethodKind is MethodKind.Constructor)
9698
{
99+
ExtractObjectInitCall(trapFile);
97100
var baseType = Symbol.ContainingType.BaseType;
98101
if (baseType is null)
99102
{
@@ -127,6 +130,27 @@ protected override void ExtractInitializers(TextWriter trapFile)
127130
}
128131
}
129132

133+
private void ExtractObjectInitCall(TextWriter trapFile)
134+
{
135+
var target = ObjectInitMethod.Create(Context, ContainingType!);
136+
137+
var type = Context.Compilation.GetSpecialType(SpecialType.System_Void);
138+
139+
var info = new ExpressionInfo(Context,
140+
AnnotatedTypeSymbol.CreateNotAnnotated(type),
141+
Location,
142+
Kinds.ExprKind.METHOD_INVOCATION,
143+
this,
144+
-2,
145+
isCompilerGenerated: true,
146+
null);
147+
var obinitCall = new Expression(info);
148+
149+
trapFile.expr_call(obinitCall, target);
150+
151+
Expressions.This.CreateImplicit(Context, Symbol.ContainingType, Location, obinitCall, -1);
152+
}
153+
130154
private void ExtractSourceInitializer(TextWriter trapFile, ITypeSymbol? type, IMethodSymbol? symbol, ArgumentListSyntax arguments, Microsoft.CodeAnalysis.Location location)
131155
{
132156
var initInfo = new ExpressionInfo(Context,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Semmle.Extraction.CSharp.Entities
2+
{
3+
/// <summary>
4+
/// Marker interface for method entities.
5+
/// </summary>
6+
public interface IMethodEntity : IEntity
7+
{
8+
}
9+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace Semmle.Extraction.CSharp.Entities
1111
{
12-
internal abstract class Method : CachedSymbol<IMethodSymbol>, IExpressionParentEntity, IStatementParentEntity
12+
internal abstract class Method : CachedSymbol<IMethodSymbol>, IExpressionParentEntity, IStatementParentEntity, IMethodEntity
1313
{
1414
protected Method(Context cx, IMethodSymbol init)
1515
: base(cx, init) { }
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
using System.IO;
2+
using Microsoft.CodeAnalysis;
3+
4+
namespace Semmle.Extraction.CSharp.Entities
5+
{
6+
internal sealed class ObjectInitMethod : CachedEntity, IMethodEntity
7+
{
8+
Type ContainingType { get; }
9+
10+
private ObjectInitMethod(Context cx, Type containingType)
11+
: base(cx)
12+
{
13+
this.ContainingType = containingType;
14+
}
15+
16+
public string Name => "<object initializer>";
17+
18+
public static ObjectInitMethod Create(Context cx, Type containingType)
19+
{
20+
return ObjectInitMethodFactory.Instance.CreateEntity(cx, (typeof(ObjectInitMethod), containingType), containingType);
21+
}
22+
23+
public override void Populate(TextWriter trapFile)
24+
{
25+
var returnType = Type.Create(Context, Context.Compilation.GetSpecialType(SpecialType.System_Void));
26+
27+
trapFile.methods(this, Name, ContainingType, returnType.TypeRef, this);
28+
29+
trapFile.compiler_generated(this);
30+
31+
trapFile.method_location(this, Context.CreateLocation(ReportingLocation));
32+
}
33+
34+
public override void WriteId(EscapingTextWriter trapFile)
35+
{
36+
trapFile.WriteSubId(ContainingType);
37+
trapFile.Write(".");
38+
trapFile.Write(Name);
39+
trapFile.Write(";method");
40+
}
41+
42+
public override Microsoft.CodeAnalysis.Location? ReportingLocation => ContainingType.ReportingLocation;
43+
44+
public override bool NeedsPopulation => true;
45+
46+
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
47+
48+
private class ObjectInitMethodFactory : CachedEntityFactory<Type, ObjectInitMethod>
49+
{
50+
public static ObjectInitMethodFactory Instance { get; } = new ObjectInitMethodFactory();
51+
52+
public override ObjectInitMethod Create(Context cx, Type containingType) =>
53+
new ObjectInitMethod(cx, containingType);
54+
}
55+
}
56+
}

csharp/extractor/Semmle.Extraction.CSharp/Trap/Tuples.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ internal static void expr_argument(this TextWriter trapFile, Expression expr, in
175175
internal static void expr_argument_name(this TextWriter trapFile, Expression expr, string name) =>
176176
trapFile.WriteTuple("expr_argument_name", expr, name);
177177

178-
internal static void expr_call(this TextWriter trapFile, Expression expr, Method target) =>
178+
internal static void expr_call(this TextWriter trapFile, Expression expr, IMethodEntity target) =>
179179
trapFile.WriteTuple("expr_call", expr, target);
180180

181181
internal static void expr_flowstate(this TextWriter trapFile, Expression expr, int flowState) =>
@@ -247,10 +247,10 @@ internal static void localvar_location(this TextWriter trapFile, LocalVariable v
247247
internal static void localvars(this TextWriter trapFile, LocalVariable key, VariableKind kind, string name, int @var, Type type, Expression expr) =>
248248
trapFile.WriteTuple("localvars", key, (int)kind, name, @var, type, expr);
249249

250-
internal static void method_location(this TextWriter trapFile, Method method, Location location) =>
250+
internal static void method_location(this TextWriter trapFile, IMethodEntity method, Location location) =>
251251
trapFile.WriteTuple("method_location", method, location);
252252

253-
internal static void methods(this TextWriter trapFile, Method method, string name, Type declType, Type retType, Method originalDefinition) =>
253+
internal static void methods(this TextWriter trapFile, IMethodEntity method, string name, Type declType, Type retType, IMethodEntity originalDefinition) =>
254254
trapFile.WriteTuple("methods", method, name, declType, retType, originalDefinition);
255255

256256
internal static void modifiers(this TextWriter trapFile, Label entity, string modifier) =>

0 commit comments

Comments
 (0)