Skip to content

Commit ab9f78f

Browse files
authored
Merge pull request #20617 from michaelnebel/csharp/unboundlocations
C#: Reduce location TRAP creation for Fields, Parameters, Constructors, Destructors and Operators.
2 parents d842107 + b8c3a28 commit ab9f78f

File tree

14 files changed

+145
-51
lines changed

14 files changed

+145
-51
lines changed

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ public override void Populate(TextWriter trapFile)
2929
ContainingType!.PopulateGenerics();
3030

3131
trapFile.constructors(this, Symbol.ContainingType.Name, ContainingType, (Constructor)OriginalDefinition);
32-
WriteLocationToTrap(trapFile.constructor_location, this, Location);
32+
if (Context.ExtractLocation(Symbol) && (!IsDefault || IsBestSourceLocation))
33+
{
34+
WriteLocationToTrap(trapFile.constructor_location, this, Location);
35+
}
3336

3437
if (MakeSynthetic)
3538
{
@@ -168,7 +171,15 @@ Symbol.ContainingType.TypeKind is TypeKind.Class or TypeKind.Struct &&
168171
Symbol.ContainingType.IsSourceDeclaration() &&
169172
!Symbol.ContainingType.IsAnonymousType;
170173

171-
private bool MakeSynthetic => IsPrimary || IsDefault;
174+
/// <summary>
175+
/// Returns true if we consider the reporting location of this constructor entity the best
176+
/// location of the constructor.
177+
/// For partial classes with default constructors, Roslyn consider each partial class declaration
178+
/// as the possible location for the implicit default constructor.
179+
/// </summary>
180+
private bool IsBestSourceLocation => ReportingLocation is not null && Context.IsLocationInContext(ReportingLocation);
181+
182+
private bool MakeSynthetic => IsPrimary || (IsDefault && IsBestSourceLocation);
172183

173184
[return: NotNullIfNotNull(nameof(constructor))]
174185
public static new Constructor? Create(Context cx, IMethodSymbol? constructor)

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ public override void Populate(TextWriter trapFile)
1515
ContainingType!.PopulateGenerics();
1616

1717
trapFile.destructors(this, $"~{Symbol.ContainingType.Name}", ContainingType, OriginalDefinition(Context, this, Symbol));
18-
WriteLocationToTrap(trapFile.destructor_location, this, Location);
18+
if (Context.ExtractLocation(Symbol))
19+
{
20+
WriteLocationToTrap(trapFile.destructor_location, this, Location);
21+
}
1922
}
2023

2124
private static new Destructor OriginalDefinition(Context cx, Destructor original, IMethodSymbol symbol)

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ public override void Populate(TextWriter trapFile)
4949
}
5050
}
5151

52-
WriteLocationsToTrap(trapFile.field_location, this, Locations);
52+
if (Context.ExtractLocation(Symbol))
53+
{
54+
WriteLocationsToTrap(trapFile.field_location, this, Locations);
55+
}
5356

5457
if (!IsSourceDeclaration || !Symbol.FromSource())
5558
return;

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,10 @@ public override void Populate(TextWriter trapFile)
115115
var type = Type.Create(Context, Symbol.Type);
116116
trapFile.@params(this, Name, type.TypeRef, Ordinal, ParamKind, Parent!, Original);
117117

118-
foreach (var l in Symbol.Locations)
118+
if (Context.ExtractLocation(Symbol))
119119
{
120-
WriteLocationToTrap(trapFile.param_location, this, Context.CreateLocation(l));
120+
var locations = Context.GetLocations(Symbol);
121+
WriteLocationsToTrap(trapFile.param_location, this, locations);
121122
}
122123

123124
if (!Symbol.Locations.Any() &&

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ public override void Populate(TextWriter trapFile)
2626
returnType.TypeRef,
2727
(UserOperator)OriginalDefinition);
2828

29-
WriteLocationsToTrap(trapFile.operator_location, this, Locations);
29+
if (Context.ExtractLocation(Symbol))
30+
{
31+
WriteLocationsToTrap(trapFile.operator_location, this, Locations);
32+
}
3033

3134
if (IsSourceDeclaration)
3235
{
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The extraction of location information for parameters, fields, constructors, destructors and user operators has been optimized. Previously, location information was extracted multiple times for each bound generic. Now, only the location of the unbound generic declaration is extracted during the extraction phase, and the QL library explicitly reuses this location for all bound instances of the same generic.

csharp/ql/lib/semmle/code/csharp/Callable.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ class Constructor extends Callable, Member, Attributable, @constructor {
357357

358358
override Constructor getUnboundDeclaration() { constructors(this, _, _, result) }
359359

360-
override Location getALocation() { constructor_location(this, result) }
360+
override Location getALocation() { constructor_location(this.getUnboundDeclaration(), result) }
361361

362362
override predicate fromSource() { Member.super.fromSource() and not this.isCompilerGenerated() }
363363

@@ -450,7 +450,7 @@ class Destructor extends Callable, Member, Attributable, @destructor {
450450

451451
override Destructor getUnboundDeclaration() { destructors(this, _, _, result) }
452452

453-
override Location getALocation() { destructor_location(this, result) }
453+
override Location getALocation() { destructor_location(this.getUnboundDeclaration(), result) }
454454

455455
override string toString() { result = Callable.super.toString() }
456456

@@ -484,7 +484,7 @@ class Operator extends Callable, Member, Attributable, Overridable, @operator {
484484

485485
override Operator getUnboundDeclaration() { operators(this, _, _, _, _, result) }
486486

487-
override Location getALocation() { operator_location(this, result) }
487+
override Location getALocation() { operator_location(this.getUnboundDeclaration(), result) }
488488

489489
override string toString() { result = Callable.super.toString() }
490490

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ class Parameter extends LocalScopeVariable, Attributable, TopLevelExprParent, @p
213213
params(this, _, getTypeRef(result), _, _, _, _)
214214
}
215215

216-
override Location getALocation() { param_location(this, result) }
216+
override Location getALocation() { param_location(this.getUnboundDeclaration(), result) }
217217

218218
override string toString() { result = this.getName() }
219219

@@ -449,7 +449,7 @@ class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent
449449
fields(this, _, _, _, getTypeRef(result), _)
450450
}
451451

452-
override Location getALocation() { field_location(this, result) }
452+
override Location getALocation() { field_location(this.getUnboundDeclaration(), result) }
453453

454454
override string toString() { result = Variable.super.toString() }
455455

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,6 @@
4343
| Assignables.cs:92:23:92:23 | b |
4444
| Assignables.cs:92:33:92:33 | s |
4545
| Assignables.cs:95:40:95:44 | tuple |
46-
| Assignables.cs:97:24:97:24 | Item1 |
47-
| Assignables.cs:97:27:97:36 | Item2 |
48-
| Assignables.cs:101:6:101:8 | Item1 |
49-
| Assignables.cs:101:11:101:24 | Item2 |
50-
| Assignables.cs:101:12:101:15 | Item1 |
51-
| Assignables.cs:101:18:101:23 | Item2 |
5246
| Assignables.cs:108:13:108:13 | i |
5347
| Assignables.cs:109:14:109:14 | p |
5448
| Assignables.cs:113:25:113:25 | i |
@@ -69,8 +63,6 @@
6963
| Assignables.cs:132:13:132:13 | x |
7064
| Assignables.cs:133:29:133:29 | s |
7165
| Assignables.cs:138:19:138:19 | x |
72-
| Discards.cs:5:6:5:8 | Item1 |
73-
| Discards.cs:5:11:5:16 | Item2 |
7466
| Discards.cs:5:30:5:30 | x |
7567
| Discards.cs:19:14:19:14 | x |
7668
| Discards.cs:20:17:20:17 | y |
Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple<int, (string, int)> | 2 | 0 | CSharp7.cs:96:19:96:19 | Item1 |
2-
| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple<int, (string, int)> | 2 | 1 | CSharp7.cs:102:22:102:46 | Item2 |
3-
| (Int32,Double) | (int, double) | ValueTuple<int, double> | 2 | 0 | CSharp7.cs:213:6:213:8 | Item1 |
4-
| (Int32,Double) | (int, double) | ValueTuple<int, double> | 2 | 1 | CSharp7.cs:213:11:213:16 | Item2 |
5-
| (Int32,Int32) | (int, int) | ValueTuple<int, int> | 2 | 0 | CSharp7.cs:62:10:62:10 | Item1 |
6-
| (Int32,Int32) | (int, int) | ValueTuple<int, int> | 2 | 1 | CSharp7.cs:62:17:62:17 | Item2 |
7-
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 0 | CSharp7.cs:95:19:95:19 | Item1 |
8-
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 1 | CSharp7.cs:95:22:95:37 | Item2 |
9-
| (String,Int32) | (string, int) | ValueTuple<string, int> | 2 | 0 | CSharp7.cs:82:17:82:17 | Item1 |
10-
| (String,Int32) | (string, int) | ValueTuple<string, int> | 2 | 1 | CSharp7.cs:82:23:82:23 | Item2 |
11-
| (String,String) | (string, string) | ValueTuple<string, string> | 2 | 0 | CSharp7.cs:87:19:87:27 | Item1 |
12-
| (String,String) | (string, string) | ValueTuple<string, string> | 2 | 1 | CSharp7.cs:87:30:87:33 | Item2 |
1+
| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple<int, (string, int)> | 2 | 0 | Item1 |
2+
| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple<int, (string, int)> | 2 | 1 | Item2 |
3+
| (Int32,Double) | (int, double) | ValueTuple<int, double> | 2 | 0 | Item1 |
4+
| (Int32,Double) | (int, double) | ValueTuple<int, double> | 2 | 1 | Item2 |
5+
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 0 | Item1 |
6+
| (Int32,String) | (int, string) | ValueTuple<int, string> | 2 | 1 | Item2 |
7+
| (String,String) | (string, string) | ValueTuple<string, string> | 2 | 0 | Item1 |
8+
| (String,String) | (string, string) | ValueTuple<string, string> | 2 | 1 | Item2 |

0 commit comments

Comments
 (0)