Skip to content

Commit b28241a

Browse files
authored
Merge pull request github#1741 from hvitved/csharp/extract-field-inits
C#: Extract assignments for field/property initializers
2 parents a6db9ef + 495e5bc commit b28241a

20 files changed

+105
-33
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using Microsoft.CodeAnalysis.CSharp.Syntax;
55
using System;
66
using Semmle.Extraction.Entities;
7+
using Semmle.Extraction.Kinds;
8+
using Semmle.Extraction.CSharp.Entities.Expressions;
79

810
namespace Semmle.Extraction.CSharp.Entities
911
{
@@ -64,7 +66,15 @@ public override void Populate()
6466
{
6567
Context.PopulateLater(() =>
6668
{
67-
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Initializer.Value, this, child++));
69+
var loc = Context.Create(initializer.GetLocation());
70+
var simpleAssignExpr = new Expression(new ExpressionInfo(Context, Type, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, null));
71+
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Initializer.Value, simpleAssignExpr, 0));
72+
var access = new Expression(new ExpressionInfo(Context, Type, Location, ExprKind.FIELD_ACCESS, simpleAssignExpr, 1, false, null));
73+
Context.Emit(Tuples.expr_access(access, this));
74+
if (!symbol.IsStatic)
75+
{
76+
This.CreateImplicit(Context, Entities.Type.Create(Context, symbol.ContainingType), Location, access, -1);
77+
}
6878
});
6979
}
7080

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using Microsoft.CodeAnalysis;
22
using Microsoft.CodeAnalysis.CSharp.Syntax;
3+
using Semmle.Extraction.CSharp.Entities.Expressions;
4+
using Semmle.Extraction.Entities;
5+
using Semmle.Extraction.Kinds;
36
using System.Linq;
47

58
namespace Semmle.Extraction.CSharp.Entities
@@ -69,12 +72,24 @@ public override void Populate()
6972
Context.PopulateLater(() => Expression.Create(Context, expressionBody, this, 0));
7073
}
7174

75+
int child = 1;
7276
foreach (var initializer in declSyntaxReferences.
7377
Select(n => n.Initializer).
74-
Where(i => i != null).
75-
Select(i => i.Value))
78+
Where(i => i != null))
7679
{
77-
Context.PopulateLater(() => Expression.Create(Context, initializer, this, 1));
80+
Context.PopulateLater(() =>
81+
{
82+
var loc = Context.Create(initializer.GetLocation());
83+
var annotatedType = new AnnotatedType(type, TypeAnnotation.None);
84+
var simpleAssignExpr = new Expression(new ExpressionInfo(Context, annotatedType, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, null));
85+
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Value, simpleAssignExpr, 0));
86+
var access = new Expression(new ExpressionInfo(Context, annotatedType, Location, ExprKind.PROPERTY_ACCESS, simpleAssignExpr, 1, false, null));
87+
Context.Emit(Tuples.expr_access(access, this));
88+
if (!symbol.IsStatic)
89+
{
90+
This.CreateImplicit(Context, Type.Create(Context, symbol.ContainingType), Location, access, -1);
91+
}
92+
});
7893
}
7994

8095
foreach (var syntax in declSyntaxReferences)

csharp/ql/src/definitions.ql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ class AccessUse extends Access, Use {
100100
not this.isImplicit() and
101101
not this instanceof MethodAccess and // handled by `MethodUse`
102102
not this instanceof TypeAccess and // handled by `TypeMentionUse`
103-
not this.(FieldAccess).getParent() instanceof Field // Enum initializer
103+
not this.(FieldAccess).getParent() instanceof Field and // Enum initializer
104+
not this.(FieldAccess).getParent().getParent() instanceof Field and // Field initializer
105+
not this.(PropertyAccess).getParent().getParent() instanceof Property // Property initializer
104106
}
105107

106108
/** Gets the qualifier of this acccess, if any. */

csharp/ql/src/semmle/code/csharp/Assignable.qll

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -315,11 +315,7 @@ module AssignableInternal {
315315
)
316316
} or
317317
TAddressOfDefinition(AddressOfExpr aoe) or
318-
TPatternDefinition(TopLevelPatternDecl tlpd) or
319-
TInitializer(Assignable a, Expr e) {
320-
e = a.(Field).getInitializer() or
321-
e = a.(Property).getInitializer()
322-
}
318+
TPatternDefinition(TopLevelPatternDecl tlpd)
323319

324320
/**
325321
* Gets the source expression assigned in tuple definition `def`, if any.
@@ -727,20 +723,12 @@ module AssignableDefinitions {
727723
* }
728724
* ```
729725
*/
730-
class InitializerDefinition extends AssignableDefinition, TInitializer {
731-
Assignable a;
726+
class InitializerDefinition extends AssignmentDefinition {
727+
private Assignable fieldOrProp;
732728

733-
Expr e;
734-
735-
InitializerDefinition() { this = TInitializer(a, e) }
729+
InitializerDefinition() { this.getAssignment().getParent() = fieldOrProp}
736730

737731
/** Gets the assignable (field or property) being initialized. */
738-
Assignable getAssignable() { result = a }
739-
740-
override Expr getSource() { result = e }
741-
742-
override string toString() { result = e.toString() }
743-
744-
override Location getLocation() { result = e.getLocation() }
732+
Assignable getAssignable() { result = fieldOrProp }
745733
}
746734
}

csharp/ql/src/semmle/code/csharp/ExprOrStmtParent.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import csharp
1515
predicate expr_parent_top_level_adjusted(Expr child, int i, @top_level_exprorstmt_parent parent) {
1616
expr_parent_top_level(child, i, parent)
1717
or
18-
parent = any(Getter g | expr_parent_top_level(child, i, g.getDeclaration()))
18+
parent = any(Getter g | expr_parent_top_level(child, i, g.getDeclaration())) and
19+
i = 0
1920
}
2021

2122
/**

csharp/ql/src/semmle/code/csharp/Property.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @proper
201201
* }
202202
* ```
203203
*/
204-
Expr getInitializer() { result = this.getChildExpr(1) }
204+
Expr getInitializer() { result = this.getChildExpr(1).getChildExpr(0) }
205205

206206
/**
207207
* Gets the expression body of this property, if any. For example, the expression

csharp/ql/src/semmle/code/csharp/Variable.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ class LocalConstant extends LocalVariable, @local_constant {
365365
class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent, DotNet::Field,
366366
@field {
367367
/** Gets the initializer of this field, if any. */
368-
override Expr getInitializer() { result = this.getChildExpr(0) }
368+
override Expr getInitializer() { result = this.getChildExpr(0).getChildExpr(0) }
369369

370370
/** Holds if this field is `volatile`. */
371371
predicate isVolatile() { this.hasModifier("volatile") }
@@ -447,4 +447,6 @@ class EnumConstant extends MemberConstant {
447447
* ```
448448
*/
449449
predicate hasExplicitValue() { exists(this.getInitializer()) }
450+
451+
override Expr getInitializer() { result = this.getChildExpr(0) }
450452
}

csharp/ql/test/library-tests/assignables/AssignableAccess.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
| Assignables.cs:5:9:5:13 | access to field Field | Assignables.cs:5:9:5:13 | Field | write |
2+
| Assignables.cs:6:9:6:16 | access to property Property | Assignables.cs:6:9:6:16 | Property | write |
13
| Assignables.cs:9:36:9:36 | access to parameter i | Assignables.cs:9:18:9:18 | i | read |
24
| Assignables.cs:13:13:13:20 | access to local variable variable | Assignables.cs:13:13:13:20 | variable | write |
35
| Assignables.cs:14:9:14:16 | access to local variable variable | Assignables.cs:13:13:13:20 | variable | write |

csharp/ql/test/library-tests/assignables/AssignableDefinition.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
| Assignables.cs:5:9:5:13 | Field | Assignables.cs:5:17:5:17 | 0 | Assignables.cs:5:17:5:17 | <none> | Assignables.cs:5:17:5:17 | 0 | certain |
1+
| Assignables.cs:5:9:5:13 | Field | Assignables.cs:5:9:5:17 | ... = ... | Assignables.cs:5:9:5:13 | access to field Field | Assignables.cs:5:17:5:17 | 0 | certain |
22
| Assignables.cs:5:9:5:13 | Field | Assignables.cs:18:9:18:24 | ... = ... | Assignables.cs:18:9:18:13 | access to field Field | Assignables.cs:18:17:18:24 | access to property Property | certain |
33
| Assignables.cs:5:9:5:13 | Field | Assignables.cs:19:9:19:15 | ...-- | Assignables.cs:19:9:19:13 | access to field Field | Assignables.cs:19:9:19:15 | <none> | certain |
44
| Assignables.cs:5:9:5:13 | Field | Assignables.cs:29:17:29:21 | access to field Field | Assignables.cs:29:17:29:21 | access to field Field | Assignables.cs:29:17:29:21 | <none> | certain |
@@ -7,7 +7,7 @@
77
| Assignables.cs:5:9:5:13 | Field | Assignables.cs:32:37:32:41 | access to field Field | Assignables.cs:32:37:32:41 | access to field Field | Assignables.cs:32:37:32:41 | <none> | uncertain |
88
| Assignables.cs:5:9:5:13 | Field | Assignables.cs:34:29:34:33 | access to field Field | Assignables.cs:34:29:34:33 | access to field Field | Assignables.cs:34:29:34:33 | <none> | uncertain |
99
| Assignables.cs:5:9:5:13 | Field | Assignables.cs:34:40:34:44 | access to field Field | Assignables.cs:34:40:34:44 | access to field Field | Assignables.cs:34:40:34:44 | <none> | uncertain |
10-
| Assignables.cs:6:9:6:16 | Property | Assignables.cs:6:34:6:34 | 1 | Assignables.cs:6:34:6:34 | <none> | Assignables.cs:6:34:6:34 | 1 | certain |
10+
| Assignables.cs:6:9:6:16 | Property | Assignables.cs:6:32:6:34 | ... = ... | Assignables.cs:6:9:6:16 | access to property Property | Assignables.cs:6:34:6:34 | 1 | certain |
1111
| Assignables.cs:6:9:6:16 | Property | Assignables.cs:20:9:20:33 | ... = ... | Assignables.cs:20:9:20:16 | access to property Property | Assignables.cs:20:20:20:33 | access to indexer | certain |
1212
| Assignables.cs:6:9:6:16 | Property | Assignables.cs:21:9:21:18 | ...++ | Assignables.cs:21:9:21:16 | access to property Property | Assignables.cs:21:9:21:18 | <none> | certain |
1313
| Assignables.cs:6:9:6:16 | Property | Assignables.cs:96:9:96:36 | ... = ... | Assignables.cs:96:10:96:17 | access to property Property | Assignables.cs:96:32:96:32 | 2 | certain |

csharp/ql/test/library-tests/assignables/AssignableDefinitionNode.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
| Assignables.cs:5:9:5:17 | ... = ... | Assignables.cs:5:9:5:17 | ... = ... |
2+
| Assignables.cs:6:32:6:34 | ... = ... | Assignables.cs:6:32:6:34 | ... = ... |
13
| Assignables.cs:9:18:9:18 | i | Assignables.cs:9:23:9:25 | enter get_Item |
24
| Assignables.cs:9:18:9:18 | i | Assignables.cs:9:41:9:43 | enter set_Item |
35
| Assignables.cs:9:41:9:43 | value | Assignables.cs:9:41:9:43 | enter set_Item |

0 commit comments

Comments
 (0)