Skip to content

Commit 65c58ed

Browse files
authored
Merge pull request #4617 from tamasvajk/feature/csharp9-implicit-obj-creation
C#: Extract 'ImplicitObjectCreationExpressionSyntax'
2 parents a79f1e1 + f12befd commit 65c58ed

File tree

18 files changed

+7367
-3295
lines changed

18 files changed

+7367
-3295
lines changed

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Factory.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ internal static Expression Create(ExpressionNodeInfo info)
8484
case SyntaxKind.ObjectCreationExpression:
8585
return ExplicitObjectCreation.Create(info);
8686

87+
case SyntaxKind.ImplicitObjectCreationExpression:
88+
return ImplicitObjectCreation.Create(info);
89+
8790
case SyntaxKind.ArrayCreationExpression:
8891
return NormalArrayCreation.Create(info);
8992

@@ -179,7 +182,7 @@ internal static Expression Create(ExpressionNodeInfo info)
179182
return ImplicitArrayCreation.Create(info);
180183

181184
case SyntaxKind.AnonymousObjectCreationExpression:
182-
return ImplicitObjectCreation.Create(info);
185+
return AnonymousObjectCreation.Create(info);
183186

184187
case SyntaxKind.ComplexElementInitializerExpression:
185188
return CollectionInitializer.Create(info);

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ObjectCreation.cs

Lines changed: 0 additions & 137 deletions
This file was deleted.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using Microsoft.CodeAnalysis.CSharp.Syntax;
4+
using Semmle.Extraction.Entities;
5+
using Semmle.Extraction.Kinds;
6+
using System.IO;
7+
8+
namespace Semmle.Extraction.CSharp.Entities.Expressions
9+
{
10+
internal class AnonymousObjectCreation : Expression<AnonymousObjectCreationExpressionSyntax>
11+
{
12+
public AnonymousObjectCreation(ExpressionNodeInfo info)
13+
: base(info.SetKind(ExprKind.OBJECT_CREATION)) { }
14+
15+
public static Expression Create(ExpressionNodeInfo info) =>
16+
new AnonymousObjectCreation(info).TryPopulate();
17+
18+
protected override void PopulateExpression(TextWriter trapFile)
19+
{
20+
var target = cx.GetSymbolInfo(Syntax);
21+
var method = (IMethodSymbol)target.Symbol;
22+
23+
if (method != null)
24+
{
25+
trapFile.expr_call(this, Method.Create(cx, method));
26+
}
27+
var child = 0;
28+
29+
var objectInitializer = Syntax.Initializers.Any() ?
30+
new Expression(new ExpressionInfo(cx, Type, Location, ExprKind.OBJECT_INIT, this, -1, false, null)) :
31+
null;
32+
33+
foreach (var init in Syntax.Initializers)
34+
{
35+
// Create an "assignment"
36+
var property = cx.GetModel(init).GetDeclaredSymbol(init);
37+
var propEntity = Property.Create(cx, property);
38+
var type = Entities.Type.Create(cx, property.GetAnnotatedType());
39+
var loc = cx.Create(init.GetLocation());
40+
41+
var assignment = new Expression(new ExpressionInfo(cx, type, loc, ExprKind.SIMPLE_ASSIGN, objectInitializer, child++, false, null));
42+
Create(cx, init.Expression, assignment, 0);
43+
Property.Create(cx, property);
44+
45+
var access = new Expression(new ExpressionInfo(cx, type, loc, ExprKind.PROPERTY_ACCESS, assignment, 1, false, null));
46+
trapFile.expr_access(access, propEntity);
47+
}
48+
}
49+
}
50+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
using System.IO;
2+
using System.Linq;
3+
using Microsoft.CodeAnalysis;
4+
using Microsoft.CodeAnalysis.CSharp;
5+
using Microsoft.CodeAnalysis.CSharp.Syntax;
6+
using Semmle.Extraction.Kinds;
7+
8+
namespace Semmle.Extraction.CSharp.Entities.Expressions
9+
{
10+
internal abstract class BaseObjectCreation<TExpressionSyntax> : Expression<TExpressionSyntax>
11+
where TExpressionSyntax : BaseObjectCreationExpressionSyntax
12+
{
13+
protected BaseObjectCreation(ExpressionNodeInfo info)
14+
: base(info.SetKind(GetKind(info.Context, (BaseObjectCreationExpressionSyntax)info.Node)))
15+
{
16+
}
17+
18+
protected override void PopulateExpression(TextWriter trapFile)
19+
{
20+
if (Syntax.ArgumentList != null)
21+
{
22+
PopulateArguments(trapFile, Syntax.ArgumentList, 0);
23+
}
24+
25+
var target = cx.GetModel(Syntax).GetSymbolInfo(Syntax);
26+
if (target.Symbol is IMethodSymbol method)
27+
{
28+
trapFile.expr_call(this, Method.Create(cx, method));
29+
}
30+
31+
if (IsDynamicObjectCreation(cx, Syntax))
32+
{
33+
if (cx.GetModel(Syntax).GetTypeInfo(Syntax).Type is INamedTypeSymbol type &&
34+
!string.IsNullOrEmpty(type.Name))
35+
{
36+
trapFile.dynamic_member_name(this, type.Name);
37+
}
38+
else
39+
{
40+
cx.ModelError(Syntax, "Unable to get name for dynamic object creation.");
41+
}
42+
}
43+
44+
if (Syntax.Initializer != null)
45+
{
46+
switch (Syntax.Initializer.Kind())
47+
{
48+
case SyntaxKind.CollectionInitializerExpression:
49+
CollectionInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1) { Type = Type });
50+
break;
51+
case SyntaxKind.ObjectInitializerExpression:
52+
ObjectInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1) { Type = Type });
53+
break;
54+
default:
55+
cx.ModelError("Unhandled initializer in object creation");
56+
break;
57+
}
58+
}
59+
}
60+
61+
private static ExprKind GetKind(Context cx, BaseObjectCreationExpressionSyntax node)
62+
{
63+
var type = cx.GetModel(node).GetTypeInfo(node).Type;
64+
return Entities.Type.IsDelegate(type as INamedTypeSymbol)
65+
? ExprKind.EXPLICIT_DELEGATE_CREATION
66+
: ExprKind.OBJECT_CREATION;
67+
}
68+
69+
private static bool IsDynamicObjectCreation(Context cx, BaseObjectCreationExpressionSyntax node)
70+
{
71+
return node.ArgumentList != null &&
72+
node.ArgumentList.Arguments.Any(arg => IsDynamic(cx, arg.Expression));
73+
}
74+
}
75+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Microsoft.CodeAnalysis.CSharp.Syntax;
2+
using System.IO;
3+
4+
namespace Semmle.Extraction.CSharp.Entities.Expressions
5+
{
6+
// new Foo(...) { ... }.
7+
internal class ExplicitObjectCreation : BaseObjectCreation<ObjectCreationExpressionSyntax>
8+
{
9+
private ExplicitObjectCreation(ExpressionNodeInfo info) : base(info) { }
10+
11+
public static Expression Create(ExpressionNodeInfo info) => new ExplicitObjectCreation(info).TryPopulate();
12+
13+
protected override void PopulateExpression(TextWriter trapFile)
14+
{
15+
base.PopulateExpression(trapFile);
16+
17+
TypeMention.Create(cx, Syntax.Type, this, Type);
18+
}
19+
}
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.IO;
2+
using Microsoft.CodeAnalysis.CSharp.Syntax;
3+
4+
namespace Semmle.Extraction.CSharp.Entities.Expressions
5+
{
6+
internal class ImplicitObjectCreation : BaseObjectCreation<ImplicitObjectCreationExpressionSyntax>
7+
{
8+
private ImplicitObjectCreation(ExpressionNodeInfo info) : base(info) { }
9+
10+
public static Expression Create(ExpressionNodeInfo info) => new ImplicitObjectCreation(info).TryPopulate();
11+
12+
protected override void PopulateExpression(TextWriter trapFile)
13+
{
14+
base.PopulateExpression(trapFile);
15+
16+
trapFile.implicitly_typed_object_creation(this);
17+
}
18+
}
19+
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,11 @@ internal static void implicitly_typed_array_creation(this TextWriter trapFile, E
301301
trapFile.WriteTuple("implicitly_typed_array_creation", array);
302302
}
303303

304+
internal static void implicitly_typed_object_creation(this TextWriter trapFile, Expression expression)
305+
{
306+
trapFile.WriteTuple("implicitly_typed_object_creation", expression);
307+
}
308+
304309
internal static void indexer_location(this TextWriter trapFile, Indexer indexer, Location location)
305310
{
306311
trapFile.WriteTuple("indexer_location", indexer, location);

csharp/ql/src/semmle/code/csharp/exprs/Creation.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ class ObjectCreation extends Call, LateBindableExpr, @object_creation_expr {
205205
*/
206206
ObjectOrCollectionInitializer getInitializer() { result = this.getChild(-1) }
207207

208+
/** Holds if the type of the created object is inferred. */
209+
predicate isImplicitlyTyped() { implicitly_typed_object_creation(this) }
210+
208211
override string toString() { result = "object creation of type " + this.getType().getName() }
209212

210213
override Expr getRawArgument(int i) {
@@ -271,6 +274,9 @@ class DelegateCreation extends Expr, @delegate_creation_expr {
271274
*/
272275
class ExplicitDelegateCreation extends DelegateCreation, @explicit_delegate_creation_expr {
273276
override string getAPrimaryQlClass() { result = "ExplicitDelegateCreation" }
277+
278+
/** Holds if the type of the created delegate is inferred. */
279+
predicate isImplicitlyTyped() { implicitly_typed_object_creation(this) }
274280
}
275281

276282
/**

csharp/ql/src/semmlecode.csharp.dbscheme

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,8 @@ case @expr.kind of
10781078

10791079
@throw_element = @throw_expr | @throw_stmt;
10801080

1081+
@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
1082+
10811083
implicitly_typed_array_creation(
10821084
unique int id: @array_creation_expr ref);
10831085

@@ -1087,6 +1089,9 @@ explicitly_sized_array_creation(
10871089
stackalloc_array_creation(
10881090
unique int id: @array_creation_expr ref);
10891091

1092+
implicitly_typed_object_creation(
1093+
unique int id: @implicitly_typeable_object_creation_expr ref);
1094+
10901095
mutator_invocation_mode(
10911096
unique int id: @operator_invocation_expr ref,
10921097
int mode: int ref /* prefix = 1, postfix = 2*/);

0 commit comments

Comments
 (0)