diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs
index 4fa035446ef5..462fd8067888 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs
@@ -29,7 +29,10 @@ public override void Populate(TextWriter trapFile)
ContainingType!.PopulateGenerics();
trapFile.constructors(this, Symbol.ContainingType.Name, ContainingType, (Constructor)OriginalDefinition);
- WriteLocationToTrap(trapFile.constructor_location, this, Location);
+ if (Context.ExtractLocation(Symbol) && (!IsDefault || IsBestSourceLocation))
+ {
+ WriteLocationToTrap(trapFile.constructor_location, this, Location);
+ }
if (MakeSynthetic)
{
@@ -168,7 +171,15 @@ Symbol.ContainingType.TypeKind is TypeKind.Class or TypeKind.Struct &&
Symbol.ContainingType.IsSourceDeclaration() &&
!Symbol.ContainingType.IsAnonymousType;
- private bool MakeSynthetic => IsPrimary || IsDefault;
+ ///
+ /// Returns true if we consider the reporting location of this constructor entity the best
+ /// location of the constructor.
+ /// For partial classes with default constructors, Roslyn consider each partial class declaration
+ /// as the possible location for the implicit default constructor.
+ ///
+ private bool IsBestSourceLocation => ReportingLocation is not null && Context.IsLocationInContext(ReportingLocation);
+
+ private bool MakeSynthetic => IsPrimary || (IsDefault && IsBestSourceLocation);
[return: NotNullIfNotNull(nameof(constructor))]
public static new Constructor? Create(Context cx, IMethodSymbol? constructor)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs
index 3d07c7d42de9..13e86792fc35 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Destructor.cs
@@ -15,7 +15,10 @@ public override void Populate(TextWriter trapFile)
ContainingType!.PopulateGenerics();
trapFile.destructors(this, $"~{Symbol.ContainingType.Name}", ContainingType, OriginalDefinition(Context, this, Symbol));
- WriteLocationToTrap(trapFile.destructor_location, this, Location);
+ if (Context.ExtractLocation(Symbol))
+ {
+ WriteLocationToTrap(trapFile.destructor_location, this, Location);
+ }
}
private static new Destructor OriginalDefinition(Context cx, Destructor original, IMethodSymbol symbol)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs
index 61b5c40e6e50..75a35c2a5f02 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs
@@ -49,7 +49,10 @@ public override void Populate(TextWriter trapFile)
}
}
- WriteLocationsToTrap(trapFile.field_location, this, Locations);
+ if (Context.ExtractLocation(Symbol))
+ {
+ WriteLocationsToTrap(trapFile.field_location, this, Locations);
+ }
if (!IsSourceDeclaration || !Symbol.FromSource())
return;
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs
index a5d208fc86fe..8b099261a10e 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs
@@ -115,9 +115,10 @@ public override void Populate(TextWriter trapFile)
var type = Type.Create(Context, Symbol.Type);
trapFile.@params(this, Name, type.TypeRef, Ordinal, ParamKind, Parent!, Original);
- foreach (var l in Symbol.Locations)
+ if (Context.ExtractLocation(Symbol))
{
- WriteLocationToTrap(trapFile.param_location, this, Context.CreateLocation(l));
+ var locations = Context.GetLocations(Symbol);
+ WriteLocationsToTrap(trapFile.param_location, this, locations);
}
if (!Symbol.Locations.Any() &&
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs
index e37d16567e1b..40a40aab556d 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs
@@ -26,7 +26,10 @@ public override void Populate(TextWriter trapFile)
returnType.TypeRef,
(UserOperator)OriginalDefinition);
- WriteLocationsToTrap(trapFile.operator_location, this, Locations);
+ if (Context.ExtractLocation(Symbol))
+ {
+ WriteLocationsToTrap(trapFile.operator_location, this, Locations);
+ }
if (IsSourceDeclaration)
{
diff --git a/csharp/ql/lib/change-notes/2025-10-10-entity-locations.md b/csharp/ql/lib/change-notes/2025-10-10-entity-locations.md
new file mode 100644
index 000000000000..72aa663febe0
--- /dev/null
+++ b/csharp/ql/lib/change-notes/2025-10-10-entity-locations.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* 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.
diff --git a/csharp/ql/lib/semmle/code/csharp/Callable.qll b/csharp/ql/lib/semmle/code/csharp/Callable.qll
index ef0d0673ce2a..44e7c3cf4ca8 100644
--- a/csharp/ql/lib/semmle/code/csharp/Callable.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Callable.qll
@@ -357,7 +357,7 @@ class Constructor extends Callable, Member, Attributable, @constructor {
override Constructor getUnboundDeclaration() { constructors(this, _, _, result) }
- override Location getALocation() { constructor_location(this, result) }
+ override Location getALocation() { constructor_location(this.getUnboundDeclaration(), result) }
override predicate fromSource() { Member.super.fromSource() and not this.isCompilerGenerated() }
@@ -450,7 +450,7 @@ class Destructor extends Callable, Member, Attributable, @destructor {
override Destructor getUnboundDeclaration() { destructors(this, _, _, result) }
- override Location getALocation() { destructor_location(this, result) }
+ override Location getALocation() { destructor_location(this.getUnboundDeclaration(), result) }
override string toString() { result = Callable.super.toString() }
@@ -484,7 +484,7 @@ class Operator extends Callable, Member, Attributable, Overridable, @operator {
override Operator getUnboundDeclaration() { operators(this, _, _, _, _, result) }
- override Location getALocation() { operator_location(this, result) }
+ override Location getALocation() { operator_location(this.getUnboundDeclaration(), result) }
override string toString() { result = Callable.super.toString() }
diff --git a/csharp/ql/lib/semmle/code/csharp/Variable.qll b/csharp/ql/lib/semmle/code/csharp/Variable.qll
index 02018c260a68..746ea6acd2f6 100644
--- a/csharp/ql/lib/semmle/code/csharp/Variable.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Variable.qll
@@ -213,7 +213,7 @@ class Parameter extends LocalScopeVariable, Attributable, TopLevelExprParent, @p
params(this, _, getTypeRef(result), _, _, _, _)
}
- override Location getALocation() { param_location(this, result) }
+ override Location getALocation() { param_location(this.getUnboundDeclaration(), result) }
override string toString() { result = this.getName() }
@@ -449,7 +449,7 @@ class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent
fields(this, _, _, _, getTypeRef(result), _)
}
- override Location getALocation() { field_location(this, result) }
+ override Location getALocation() { field_location(this.getUnboundDeclaration(), result) }
override string toString() { result = Variable.super.toString() }
diff --git a/csharp/ql/test/library-tests/assignables/Assignables.expected b/csharp/ql/test/library-tests/assignables/Assignables.expected
index 6c11ac4869a8..97c22cd91275 100644
--- a/csharp/ql/test/library-tests/assignables/Assignables.expected
+++ b/csharp/ql/test/library-tests/assignables/Assignables.expected
@@ -43,12 +43,6 @@
| Assignables.cs:92:23:92:23 | b |
| Assignables.cs:92:33:92:33 | s |
| Assignables.cs:95:40:95:44 | tuple |
-| Assignables.cs:97:24:97:24 | Item1 |
-| Assignables.cs:97:27:97:36 | Item2 |
-| Assignables.cs:101:6:101:8 | Item1 |
-| Assignables.cs:101:11:101:24 | Item2 |
-| Assignables.cs:101:12:101:15 | Item1 |
-| Assignables.cs:101:18:101:23 | Item2 |
| Assignables.cs:108:13:108:13 | i |
| Assignables.cs:109:14:109:14 | p |
| Assignables.cs:113:25:113:25 | i |
@@ -69,8 +63,6 @@
| Assignables.cs:132:13:132:13 | x |
| Assignables.cs:133:29:133:29 | s |
| Assignables.cs:138:19:138:19 | x |
-| Discards.cs:5:6:5:8 | Item1 |
-| Discards.cs:5:11:5:16 | Item2 |
| Discards.cs:5:30:5:30 | x |
| Discards.cs:19:14:19:14 | x |
| Discards.cs:20:17:20:17 | y |
diff --git a/csharp/ql/test/library-tests/csharp7/TupleTypes.expected b/csharp/ql/test/library-tests/csharp7/TupleTypes.expected
index 9d7f3330151b..86bd4d542b99 100644
--- a/csharp/ql/test/library-tests/csharp7/TupleTypes.expected
+++ b/csharp/ql/test/library-tests/csharp7/TupleTypes.expected
@@ -1,12 +1,8 @@
-| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple | 2 | 0 | CSharp7.cs:96:19:96:19 | Item1 |
-| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple | 2 | 1 | CSharp7.cs:102:22:102:46 | Item2 |
-| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:213:6:213:8 | Item1 |
-| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:213:11:213:16 | Item2 |
-| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:62:10:62:10 | Item1 |
-| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:62:17:62:17 | Item2 |
-| (Int32,String) | (int, string) | ValueTuple | 2 | 0 | CSharp7.cs:95:19:95:19 | Item1 |
-| (Int32,String) | (int, string) | ValueTuple | 2 | 1 | CSharp7.cs:95:22:95:37 | Item2 |
-| (String,Int32) | (string, int) | ValueTuple | 2 | 0 | CSharp7.cs:82:17:82:17 | Item1 |
-| (String,Int32) | (string, int) | ValueTuple | 2 | 1 | CSharp7.cs:82:23:82:23 | Item2 |
-| (String,String) | (string, string) | ValueTuple | 2 | 0 | CSharp7.cs:87:19:87:27 | Item1 |
-| (String,String) | (string, string) | ValueTuple | 2 | 1 | CSharp7.cs:87:30:87:33 | Item2 |
+| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple | 2 | 0 | Item1 |
+| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple | 2 | 1 | Item2 |
+| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | Item1 |
+| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | Item2 |
+| (Int32,String) | (int, string) | ValueTuple | 2 | 0 | Item1 |
+| (Int32,String) | (int, string) | ValueTuple | 2 | 1 | Item2 |
+| (String,String) | (string, string) | ValueTuple | 2 | 0 | Item1 |
+| (String,String) | (string, string) | ValueTuple | 2 | 1 | Item2 |
diff --git a/csharp/ql/test/library-tests/csharp7/TupleTypes.ql b/csharp/ql/test/library-tests/csharp7/TupleTypes.ql
index 288fe1bfe982..c8fd4ac9ab03 100644
--- a/csharp/ql/test/library-tests/csharp7/TupleTypes.ql
+++ b/csharp/ql/test/library-tests/csharp7/TupleTypes.ql
@@ -1,6 +1,6 @@
import csharp
from TupleType tt, int i
-where tt.getAnElement().fromSource()
+where tt.fromSource()
select tt.getName(), tt.toStringWithTypes(), tt.getUnderlyingType().toStringWithTypes(),
- tt.getArity(), i, tt.getElement(i)
+ tt.getArity(), i, tt.getElement(i).getName()
diff --git a/csharp/ql/test/library-tests/locations/A.cs b/csharp/ql/test/library-tests/locations/A.cs
index 7f641a0024e8..565683622da9 100644
--- a/csharp/ql/test/library-tests/locations/A.cs
+++ b/csharp/ql/test/library-tests/locations/A.cs
@@ -5,8 +5,13 @@ public abstract class A
public abstract T Prop { get; }
public abstract T this[int index] { get; set; }
public abstract event EventHandler Event;
- public void Apply(T t) { }
- public abstract object ToObject(T t);
+ public void Apply(T t1) { }
+ public abstract object ToObject(T t2);
+ public object Field;
+ public A() { }
+ public A(T t) { }
+ ~A() { }
+ public static A operator +(A a1, A a2) { return a1; }
}
public class A2 : A
diff --git a/csharp/ql/test/library-tests/locations/locations.expected b/csharp/ql/test/library-tests/locations/locations.expected
index 1710f4e3cec3..d41369ddcd40 100644
--- a/csharp/ql/test/library-tests/locations/locations.expected
+++ b/csharp/ql/test/library-tests/locations/locations.expected
@@ -4,32 +4,62 @@ member_locations
| A.cs:3:23:3:26 | A | A.cs:7:40:7:44 | Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A | A.cs:8:17:8:21 | Apply | A.cs:8:17:8:21 | A.cs:8:17:8:21 |
| A.cs:3:23:3:26 | A | A.cs:9:28:9:35 | ToObject | A.cs:9:28:9:35 | A.cs:9:28:9:35 |
+| A.cs:3:23:3:26 | A | A.cs:10:19:10:23 | Field | A.cs:10:19:10:23 | A.cs:10:19:10:23 |
+| A.cs:3:23:3:26 | A | A.cs:11:12:11:12 | A | A.cs:11:12:11:12 | A.cs:11:12:11:12 |
+| A.cs:3:23:3:26 | A | A.cs:12:12:12:12 | A | A.cs:12:12:12:12 | A.cs:12:12:12:12 |
+| A.cs:3:23:3:26 | A | A.cs:13:6:13:6 | ~A | A.cs:13:6:13:6 | A.cs:13:6:13:6 |
+| A.cs:3:23:3:26 | A | A.cs:14:33:14:33 | + | A.cs:14:33:14:33 | A.cs:14:33:14:33 |
| A.cs:3:23:3:26 | A | A.cs:5:23:5:26 | Prop | A.cs:5:23:5:26 | A.cs:5:23:5:26 |
| A.cs:3:23:3:26 | A | A.cs:6:23:6:26 | Item | A.cs:6:23:6:26 | A.cs:6:23:6:26 |
| A.cs:3:23:3:26 | A | A.cs:7:40:7:44 | Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A | A.cs:8:17:8:21 | Apply | A.cs:8:17:8:21 | A.cs:8:17:8:21 |
| A.cs:3:23:3:26 | A | A.cs:9:28:9:35 | ToObject | A.cs:9:28:9:35 | A.cs:9:28:9:35 |
+| A.cs:3:23:3:26 | A | A.cs:10:19:10:23 | Field | A.cs:10:19:10:23 | A.cs:10:19:10:23 |
+| A.cs:3:23:3:26 | A | A.cs:11:12:11:12 | A | A.cs:11:12:11:12 | A.cs:11:12:11:12 |
+| A.cs:3:23:3:26 | A | A.cs:12:12:12:12 | A | A.cs:12:12:12:12 | A.cs:12:12:12:12 |
+| A.cs:3:23:3:26 | A | A.cs:13:6:13:6 | ~A | A.cs:13:6:13:6 | A.cs:13:6:13:6 |
+| A.cs:3:23:3:26 | A | A.cs:14:33:14:33 | + | A.cs:14:33:14:33 | A.cs:14:33:14:33 |
| A.cs:3:23:3:26 | A`1 | A.cs:5:23:5:26 | Prop | A.cs:5:23:5:26 | A.cs:5:23:5:26 |
| A.cs:3:23:3:26 | A`1 | A.cs:6:23:6:26 | Item | A.cs:6:23:6:26 | A.cs:6:23:6:26 |
| A.cs:3:23:3:26 | A`1 | A.cs:7:40:7:44 | Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A`1 | A.cs:8:17:8:21 | Apply | A.cs:8:17:8:21 | A.cs:8:17:8:21 |
| A.cs:3:23:3:26 | A`1 | A.cs:9:28:9:35 | ToObject | A.cs:9:28:9:35 | A.cs:9:28:9:35 |
-| A.cs:12:14:12:15 | A2 | A.cs:14:28:14:31 | Prop | A.cs:14:28:14:31 | A.cs:14:28:14:31 |
-| A.cs:12:14:12:15 | A2 | A.cs:16:28:16:31 | Item | A.cs:16:28:16:31 | A.cs:16:28:16:31 |
-| A.cs:12:14:12:15 | A2 | A.cs:22:40:22:44 | Event | A.cs:22:40:22:44 | A.cs:22:40:22:44 |
-| A.cs:12:14:12:15 | A2 | A.cs:28:28:28:35 | ToObject | A.cs:28:28:28:35 | A.cs:28:28:28:35 |
-| A.cs:12:14:12:15 | A2 | A.cs:30:17:30:17 | M | A.cs:30:17:30:17 | A.cs:30:17:30:17 |
+| A.cs:3:23:3:26 | A`1 | A.cs:10:19:10:23 | Field | A.cs:10:19:10:23 | A.cs:10:19:10:23 |
+| A.cs:3:23:3:26 | A`1 | A.cs:11:12:11:12 | A | A.cs:11:12:11:12 | A.cs:11:12:11:12 |
+| A.cs:3:23:3:26 | A`1 | A.cs:12:12:12:12 | A | A.cs:12:12:12:12 | A.cs:12:12:12:12 |
+| A.cs:3:23:3:26 | A`1 | A.cs:13:6:13:6 | ~A | A.cs:13:6:13:6 | A.cs:13:6:13:6 |
+| A.cs:3:23:3:26 | A`1 | A.cs:14:33:14:33 | + | A.cs:14:33:14:33 | A.cs:14:33:14:33 |
+| A.cs:17:14:17:15 | A2 | A.cs:17:14:17:15 | A2 | A.cs:17:14:17:15 | A.cs:17:14:17:15 |
+| A.cs:17:14:17:15 | A2 | A.cs:19:28:19:31 | Prop | A.cs:19:28:19:31 | A.cs:19:28:19:31 |
+| A.cs:17:14:17:15 | A2 | A.cs:21:28:21:31 | Item | A.cs:21:28:21:31 | A.cs:21:28:21:31 |
+| A.cs:17:14:17:15 | A2 | A.cs:27:40:27:44 | Event | A.cs:27:40:27:44 | A.cs:27:40:27:44 |
+| A.cs:17:14:17:15 | A2 | A.cs:33:28:33:35 | ToObject | A.cs:33:28:33:35 | A.cs:33:28:33:35 |
+| A.cs:17:14:17:15 | A2 | A.cs:35:17:35:17 | M | A.cs:35:17:35:17 | A.cs:35:17:35:17 |
+| B.cs:3:14:3:14 | B | B.cs:3:14:3:14 | B | B.cs:3:14:3:14 | B.cs:3:14:3:14 |
| B.cs:3:14:3:14 | B | B.cs:5:25:5:28 | Prop | B.cs:5:25:5:28 | B.cs:5:25:5:28 |
| B.cs:3:14:3:14 | B | B.cs:7:25:7:28 | Item | B.cs:7:25:7:28 | B.cs:7:25:7:28 |
| B.cs:3:14:3:14 | B | B.cs:13:40:13:44 | Event | B.cs:13:40:13:44 | B.cs:13:40:13:44 |
| B.cs:3:14:3:14 | B | B.cs:19:28:19:35 | ToObject | B.cs:19:28:19:35 | B.cs:19:28:19:35 |
+| Base.cs:1:23:1:29 | Base | Base.cs:1:23:1:26 | Base | Base.cs:1:23:1:26 | Base.cs:1:23:1:26 |
| Base.cs:1:23:1:29 | Base | Base.cs:3:17:3:17 | M | Base.cs:3:17:3:17 | Base.cs:3:17:3:17 |
| Base.cs:1:23:1:29 | Base | Base.cs:5:18:5:26 | InnerBase | Base.cs:5:18:5:26 | Base.cs:5:18:5:26 |
+| Base.cs:1:23:1:29 | Base`1 | Base.cs:1:23:1:26 | Base | Base.cs:1:23:1:26 | Base.cs:1:23:1:26 |
| Base.cs:1:23:1:29 | Base`1 | Base.cs:3:17:3:17 | M | Base.cs:3:17:3:17 | Base.cs:3:17:3:17 |
| Base.cs:1:23:1:29 | Base`1 | Base.cs:5:18:5:26 | InnerBase | Base.cs:5:18:5:26 | Base.cs:5:18:5:26 |
+| Base.cs:5:18:5:26 | InnerBase | Base.cs:5:18:5:26 | InnerBase | Base.cs:5:18:5:26 | Base.cs:5:18:5:26 |
+| Base.cs:5:18:5:26 | InnerBase | Base.cs:5:18:5:26 | InnerBase | Base.cs:5:18:5:26 | Base.cs:5:18:5:26 |
+| Base.cs:8:23:8:30 | Base2`1 | Base.cs:8:23:8:27 | Base2 | Base.cs:8:23:8:27 | Base.cs:8:23:8:27 |
+| C.cs:3:7:3:7 | C | C.cs:3:7:3:7 | C | C.cs:3:7:3:7 | C.cs:3:7:3:7 |
| C.cs:3:7:3:7 | C | C.cs:5:17:5:17 | M | C.cs:5:17:5:17 | C.cs:5:17:5:17 |
+| Multiple1.cs:1:22:1:29 | Multiple | Multiple1.cs:1:22:1:29 | Multiple | Multiple1.cs:1:22:1:29 | Multiple1.cs:1:22:1:29 |
+| Multiple1.cs:3:22:3:39 | MultipleGeneric`1 | Multiple1.cs:3:22:3:36 | MultipleGeneric | Multiple1.cs:3:22:3:36 | Multiple1.cs:3:22:3:36 |
+| Multiple1.cs:5:14:5:30 | Multiple1Specific | Multiple1.cs:5:14:5:30 | Multiple1Specific | Multiple1.cs:5:14:5:30 | Multiple1.cs:5:14:5:30 |
| Multiple1.cs:5:14:5:30 | Multiple1Specific | Multiple1.cs:7:33:7:33 | M | Multiple1.cs:7:33:7:33 | Multiple1.cs:7:33:7:33 |
+| Multiple2.cs:1:22:1:29 | Multiple | Multiple1.cs:1:22:1:29 | Multiple | Multiple1.cs:1:22:1:29 | Multiple1.cs:1:22:1:29 |
+| Multiple2.cs:3:22:3:39 | MultipleGeneric`1 | Multiple1.cs:3:22:3:36 | MultipleGeneric | Multiple1.cs:3:22:3:36 | Multiple1.cs:3:22:3:36 |
+| Multiple2.cs:5:14:5:30 | Multiple2Specific | Multiple2.cs:5:14:5:30 | Multiple2Specific | Multiple2.cs:5:14:5:30 | Multiple2.cs:5:14:5:30 |
| Multiple2.cs:5:14:5:30 | Multiple2Specific | Multiple2.cs:7:17:7:17 | M | Multiple2.cs:7:17:7:17 | Multiple2.cs:7:17:7:17 |
+| Sub.cs:1:14:1:16 | Sub | Sub.cs:1:14:1:16 | Sub | Sub.cs:1:14:1:16 | Sub.cs:1:14:1:16 |
| Sub.cs:1:14:1:16 | Sub | Sub.cs:3:17:3:20 | SubM | Sub.cs:3:17:3:20 | Sub.cs:3:17:3:20 |
accessor_location
| A.cs:3:23:3:26 | A | A.cs:5:30:5:32 | get_Prop | A.cs:5:30:5:32 | A.cs:5:30:5:32 |
@@ -47,11 +77,11 @@ accessor_location
| A.cs:3:23:3:26 | A`1 | A.cs:6:46:6:48 | set_Item | A.cs:6:46:6:48 | A.cs:6:46:6:48 |
| A.cs:3:23:3:26 | A`1 | A.cs:7:40:7:44 | add_Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A`1 | A.cs:7:40:7:44 | remove_Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
-| A.cs:12:14:12:15 | A2 | A.cs:14:36:14:37 | get_Prop | A.cs:14:36:14:37 | A.cs:14:36:14:37 |
-| A.cs:12:14:12:15 | A2 | A.cs:18:9:18:11 | get_Item | A.cs:18:9:18:11 | A.cs:18:9:18:11 |
-| A.cs:12:14:12:15 | A2 | A.cs:19:9:19:11 | set_Item | A.cs:19:9:19:11 | A.cs:19:9:19:11 |
-| A.cs:12:14:12:15 | A2 | A.cs:24:9:24:11 | add_Event | A.cs:24:9:24:11 | A.cs:24:9:24:11 |
-| A.cs:12:14:12:15 | A2 | A.cs:25:9:25:14 | remove_Event | A.cs:25:9:25:14 | A.cs:25:9:25:14 |
+| A.cs:17:14:17:15 | A2 | A.cs:19:36:19:37 | get_Prop | A.cs:19:36:19:37 | A.cs:19:36:19:37 |
+| A.cs:17:14:17:15 | A2 | A.cs:23:9:23:11 | get_Item | A.cs:23:9:23:11 | A.cs:23:9:23:11 |
+| A.cs:17:14:17:15 | A2 | A.cs:24:9:24:11 | set_Item | A.cs:24:9:24:11 | A.cs:24:9:24:11 |
+| A.cs:17:14:17:15 | A2 | A.cs:29:9:29:11 | add_Event | A.cs:29:9:29:11 | A.cs:29:9:29:11 |
+| A.cs:17:14:17:15 | A2 | A.cs:30:9:30:14 | remove_Event | A.cs:30:9:30:14 | A.cs:30:9:30:14 |
| B.cs:3:14:3:14 | B | B.cs:5:33:5:33 | get_Prop | B.cs:5:33:5:33 | B.cs:5:33:5:33 |
| B.cs:3:14:3:14 | B | B.cs:9:9:9:11 | get_Item | B.cs:9:9:9:11 | B.cs:9:9:9:11 |
| B.cs:3:14:3:14 | B | B.cs:10:9:10:11 | set_Item | B.cs:10:9:10:11 | B.cs:10:9:10:11 |
@@ -62,7 +92,7 @@ type_location
| A.cs:3:23:3:26 | A | A.cs:3:23:3:26 | A.cs:3:23:3:26 |
| A.cs:3:23:3:26 | A`1 | A.cs:3:23:3:26 | A.cs:3:23:3:26 |
| A.cs:3:25:3:25 | T | A.cs:3:25:3:25 | A.cs:3:25:3:25 |
-| A.cs:12:14:12:15 | A2 | A.cs:12:14:12:15 | A.cs:12:14:12:15 |
+| A.cs:17:14:17:15 | A2 | A.cs:17:14:17:15 | A.cs:17:14:17:15 |
| B.cs:3:14:3:14 | B | B.cs:3:14:3:14 | B.cs:3:14:3:14 |
| Base.cs:1:23:1:29 | Base | Base.cs:1:23:1:29 | Base.cs:1:23:1:29 |
| Base.cs:1:23:1:29 | Base`1 | Base.cs:1:23:1:29 | Base.cs:1:23:1:29 |
@@ -87,11 +117,11 @@ type_location
| Multiple2.cs:5:14:5:30 | Multiple2Specific | Multiple2.cs:5:14:5:30 | Multiple2.cs:5:14:5:30 |
| Sub.cs:1:14:1:16 | Sub | Sub.cs:1:14:1:16 | Sub.cs:1:14:1:16 |
calltype_location
-| A.cs:12:14:12:15 | call to constructor A | A.cs:3:23:3:26 | A | A.cs:3:23:3:26 | A.cs:3:23:3:26 |
-| A.cs:32:20:32:24 | object creation of type A2 | A.cs:12:14:12:15 | A2 | A.cs:12:14:12:15 | A.cs:12:14:12:15 |
+| A.cs:17:14:17:15 | call to constructor A | A.cs:3:23:3:26 | A | A.cs:3:23:3:26 | A.cs:3:23:3:26 |
+| A.cs:37:20:37:24 | object creation of type A2 | A.cs:17:14:17:15 | A2 | A.cs:17:14:17:15 | A.cs:17:14:17:15 |
| B.cs:3:14:3:14 | call to constructor A | A.cs:3:23:3:26 | A | A.cs:3:23:3:26 | A.cs:3:23:3:26 |
| C.cs:7:15:7:21 | object creation of type B | B.cs:3:14:3:14 | B | B.cs:3:14:3:14 | B.cs:3:14:3:14 |
-| C.cs:9:17:9:24 | object creation of type A2 | A.cs:12:14:12:15 | A2 | A.cs:12:14:12:15 | A.cs:12:14:12:15 |
+| C.cs:9:17:9:24 | object creation of type A2 | A.cs:17:14:17:15 | A2 | A.cs:17:14:17:15 | A.cs:17:14:17:15 |
| Sub.cs:1:14:1:16 | call to constructor Base | Base.cs:1:23:1:29 | Base | Base.cs:1:23:1:29 | Base.cs:1:23:1:29 |
| Sub.cs:6:17:6:31 | object creation of type InnerBase | Base.cs:5:18:5:26 | InnerBase | Base.cs:5:18:5:26 | Base.cs:5:18:5:26 |
typeparameter_location
@@ -104,3 +134,46 @@ tupletype_location
| Multiple1.cs:7:19:7:31 | (Int32,String) | Multiple1.cs:7:19:7:31 | Multiple1.cs:7:19:7:31 |
| Multiple1.cs:7:19:7:31 | (Int32,String) | Multiple2.cs:9:9:9:21 | Multiple2.cs:9:9:9:21 |
| Multiple1.cs:10:9:10:18 | (Int32,Int32) | Multiple1.cs:10:9:10:18 | Multiple1.cs:10:9:10:18 |
+parameter_locations
+| A.cs:6:41:6:43 | get_Item | A.cs:6:32:6:36 | index | A.cs:6:32:6:36 | A.cs:6:32:6:36 |
+| A.cs:6:41:6:43 | get_Item | A.cs:6:32:6:36 | index | A.cs:6:32:6:36 | A.cs:6:32:6:36 |
+| A.cs:6:41:6:43 | get_Item | A.cs:6:32:6:36 | index | A.cs:6:32:6:36 | A.cs:6:32:6:36 |
+| A.cs:6:46:6:48 | set_Item | A.cs:6:32:6:36 | index | A.cs:6:32:6:36 | A.cs:6:32:6:36 |
+| A.cs:6:46:6:48 | set_Item | A.cs:6:32:6:36 | index | A.cs:6:32:6:36 | A.cs:6:32:6:36 |
+| A.cs:6:46:6:48 | set_Item | A.cs:6:32:6:36 | index | A.cs:6:32:6:36 | A.cs:6:32:6:36 |
+| A.cs:6:46:6:48 | set_Item | A.cs:6:46:6:48 | value | A.cs:6:46:6:48 | A.cs:6:46:6:48 |
+| A.cs:6:46:6:48 | set_Item | A.cs:6:46:6:48 | value | A.cs:6:46:6:48 | A.cs:6:46:6:48 |
+| A.cs:6:46:6:48 | set_Item | A.cs:6:46:6:48 | value | A.cs:6:46:6:48 | A.cs:6:46:6:48 |
+| A.cs:7:40:7:44 | add_Event | A.cs:7:40:7:44 | value | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
+| A.cs:7:40:7:44 | add_Event | A.cs:7:40:7:44 | value | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
+| A.cs:7:40:7:44 | add_Event | A.cs:7:40:7:44 | value | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
+| A.cs:7:40:7:44 | remove_Event | A.cs:7:40:7:44 | value | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
+| A.cs:7:40:7:44 | remove_Event | A.cs:7:40:7:44 | value | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
+| A.cs:7:40:7:44 | remove_Event | A.cs:7:40:7:44 | value | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
+| A.cs:8:17:8:21 | Apply | A.cs:8:25:8:26 | t1 | A.cs:8:25:8:26 | A.cs:8:25:8:26 |
+| A.cs:8:17:8:21 | Apply | A.cs:8:25:8:26 | t1 | A.cs:8:25:8:26 | A.cs:8:25:8:26 |
+| A.cs:8:17:8:21 | Apply | A.cs:8:25:8:26 | t1 | A.cs:8:25:8:26 | A.cs:8:25:8:26 |
+| A.cs:9:28:9:35 | ToObject | A.cs:9:39:9:40 | t2 | A.cs:9:39:9:40 | A.cs:9:39:9:40 |
+| A.cs:9:28:9:35 | ToObject | A.cs:9:39:9:40 | t2 | A.cs:9:39:9:40 | A.cs:9:39:9:40 |
+| A.cs:9:28:9:35 | ToObject | A.cs:9:39:9:40 | t2 | A.cs:9:39:9:40 | A.cs:9:39:9:40 |
+| A.cs:12:12:12:12 | A | A.cs:12:16:12:16 | t | A.cs:12:16:12:16 | A.cs:12:16:12:16 |
+| A.cs:12:12:12:12 | A | A.cs:12:16:12:16 | t | A.cs:12:16:12:16 | A.cs:12:16:12:16 |
+| A.cs:12:12:12:12 | A | A.cs:12:16:12:16 | t | A.cs:12:16:12:16 | A.cs:12:16:12:16 |
+| A.cs:14:33:14:33 | + | A.cs:14:40:14:41 | a1 | A.cs:14:40:14:41 | A.cs:14:40:14:41 |
+| A.cs:14:33:14:33 | + | A.cs:14:40:14:41 | a1 | A.cs:14:40:14:41 | A.cs:14:40:14:41 |
+| A.cs:14:33:14:33 | + | A.cs:14:40:14:41 | a1 | A.cs:14:40:14:41 | A.cs:14:40:14:41 |
+| A.cs:14:33:14:33 | + | A.cs:14:49:14:50 | a2 | A.cs:14:49:14:50 | A.cs:14:49:14:50 |
+| A.cs:14:33:14:33 | + | A.cs:14:49:14:50 | a2 | A.cs:14:49:14:50 | A.cs:14:49:14:50 |
+| A.cs:14:33:14:33 | + | A.cs:14:49:14:50 | a2 | A.cs:14:49:14:50 | A.cs:14:49:14:50 |
+| A.cs:23:9:23:11 | get_Item | A.cs:21:37:21:37 | i | A.cs:21:37:21:37 | A.cs:21:37:21:37 |
+| A.cs:24:9:24:11 | set_Item | A.cs:21:37:21:37 | i | A.cs:21:37:21:37 | A.cs:21:37:21:37 |
+| A.cs:24:9:24:11 | set_Item | A.cs:24:9:24:11 | value | A.cs:24:9:24:11 | A.cs:24:9:24:11 |
+| A.cs:29:9:29:11 | add_Event | A.cs:29:9:29:11 | value | A.cs:29:9:29:11 | A.cs:29:9:29:11 |
+| A.cs:30:9:30:14 | remove_Event | A.cs:30:9:30:14 | value | A.cs:30:9:30:14 | A.cs:30:9:30:14 |
+| A.cs:33:28:33:35 | ToObject | A.cs:33:44:33:44 | t | A.cs:33:44:33:44 | A.cs:33:44:33:44 |
+| B.cs:9:9:9:11 | get_Item | B.cs:7:34:7:34 | i | B.cs:7:34:7:34 | B.cs:7:34:7:34 |
+| B.cs:10:9:10:11 | set_Item | B.cs:7:34:7:34 | i | B.cs:7:34:7:34 | B.cs:7:34:7:34 |
+| B.cs:10:9:10:11 | set_Item | B.cs:10:9:10:11 | value | B.cs:10:9:10:11 | B.cs:10:9:10:11 |
+| B.cs:15:9:15:11 | add_Event | B.cs:15:9:15:11 | value | B.cs:15:9:15:11 | B.cs:15:9:15:11 |
+| B.cs:16:9:16:14 | remove_Event | B.cs:16:9:16:14 | value | B.cs:16:9:16:14 | B.cs:16:9:16:14 |
+| B.cs:19:28:19:35 | ToObject | B.cs:19:41:19:41 | t | B.cs:19:41:19:41 | B.cs:19:41:19:41 |
diff --git a/csharp/ql/test/library-tests/locations/locations.ql b/csharp/ql/test/library-tests/locations/locations.ql
index 670a27408115..d97852d7b3b5 100644
--- a/csharp/ql/test/library-tests/locations/locations.ql
+++ b/csharp/ql/test/library-tests/locations/locations.ql
@@ -4,7 +4,6 @@ query predicate member_locations(Type t, Member m, SourceLocation l) {
t = m.getDeclaringType() and
l = m.getLocation() and
not l instanceof EmptyLocation and
- not m instanceof Constructor and
t.fromSource()
}
@@ -26,3 +25,7 @@ query predicate calltype_location(Call call, Type t, SourceLocation l) {
query predicate typeparameter_location(TypeParameter tp, SourceLocation l) { tp.getALocation() = l }
query predicate tupletype_location(TupleType tt, SourceLocation l) { tt.getALocation() = l }
+
+query predicate parameter_locations(Callable c, Parameter p, SourceLocation l) {
+ p.getCallable() = c and p.getALocation() = l
+}