diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs index 25c8926e3e0..8c93d630d15 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs @@ -250,41 +250,44 @@ namespace Semmle.Extraction.CSharp.Entities /// public void PopulateGenerics() { - if (Symbol is null || !NeedsPopulation || !Context.ExtractGenerics(this)) - return; - - var members = new List(); - - foreach (var member in Symbol.GetMembers()) - members.Add(member); - foreach (var member in Symbol.GetTypeMembers()) - members.Add(member); - - // Mono extractor puts all BASE interface members as members of the current interface. - - if (Symbol.TypeKind == TypeKind.Interface) + Context.PopulateLater(() => { - foreach (var baseInterface in Symbol.Interfaces) + if (Symbol is null || !NeedsPopulation || !Context.ExtractGenerics(this)) + return; + + var members = new List(); + + foreach (var member in Symbol.GetMembers()) + members.Add(member); + foreach (var member in Symbol.GetTypeMembers()) + members.Add(member); + + // Mono extractor puts all BASE interface members as members of the current interface. + + if (Symbol.TypeKind == TypeKind.Interface) { - foreach (var member in baseInterface.GetMembers()) - members.Add(member); - foreach (var member in baseInterface.GetTypeMembers()) - members.Add(member); + foreach (var baseInterface in Symbol.Interfaces) + { + foreach (var member in baseInterface.GetMembers()) + members.Add(member); + foreach (var member in baseInterface.GetTypeMembers()) + members.Add(member); + } } - } - foreach (var member in members) - { - Context.CreateEntity(member); - } + foreach (var member in members) + { + Context.CreateEntity(member); + } - if (Symbol.BaseType is not null) - Create(Context, Symbol.BaseType).PopulateGenerics(); + if (Symbol.BaseType is not null) + Create(Context, Symbol.BaseType).PopulateGenerics(); - foreach (var i in Symbol.Interfaces) - { - Create(Context, i).PopulateGenerics(); - } + foreach (var i in Symbol.Interfaces) + { + Create(Context, i).PopulateGenerics(); + } + }, preserveDuplicationKey: false); } public void ExtractRecursive(TextWriter trapFile, IEntity parent) diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs index 6694757f0d8..a6442758daf 100644 --- a/csharp/extractor/Semmle.Extraction/Context.cs +++ b/csharp/extractor/Semmle.Extraction/Context.cs @@ -153,9 +153,9 @@ namespace Semmle.Extraction /// Enqueue the given action to be performed later. /// /// The action to run. - public void PopulateLater(Action a) + public void PopulateLater(Action a, bool preserveDuplicationKey = true) { - var key = GetCurrentTagStackKey(); + var key = preserveDuplicationKey ? GetCurrentTagStackKey() : null; if (key is not null) { // If we are currently executing with a duplication guard, then the same diff --git a/csharp/ql/test/library-tests/csharp7/TupleExpr.expected b/csharp/ql/test/library-tests/csharp7/TupleExpr.expected index ed5c61051c1..66ceb61382b 100644 --- a/csharp/ql/test/library-tests/csharp7/TupleExpr.expected +++ b/csharp/ql/test/library-tests/csharp7/TupleExpr.expected @@ -40,8 +40,8 @@ | CSharp7.cs:87:18:87:34 | (..., ...) | CSharp7.cs:87:18:87:34 | (String,String) | 1 | CSharp7.cs:87:30:87:33 | "X2" | | CSharp7.cs:88:9:88:24 | (..., ...) | CSharp7.cs:87:18:87:34 | (String,String) | 0 | CSharp7.cs:88:14:88:15 | String t2 | | CSharp7.cs:88:9:88:24 | (..., ...) | CSharp7.cs:87:18:87:34 | (String,String) | 1 | CSharp7.cs:88:22:88:23 | String t3 | -| CSharp7.cs:95:18:95:38 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 0 | CSharp7.cs:95:19:95:19 | 1 | -| CSharp7.cs:95:18:95:38 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 1 | CSharp7.cs:95:22:95:37 | "TupleExprNode1" | +| CSharp7.cs:95:18:95:38 | (..., ...) | CSharp7.cs:95:18:95:38 | (Int32,String) | 0 | CSharp7.cs:95:19:95:19 | 1 | +| CSharp7.cs:95:18:95:38 | (..., ...) | CSharp7.cs:95:18:95:38 | (Int32,String) | 1 | CSharp7.cs:95:22:95:37 | "TupleExprNode1" | | CSharp7.cs:96:18:96:43 | (..., ...) | CSharp7.cs:96:18:96:43 | (Int32,(String,Int32)) | 0 | CSharp7.cs:96:19:96:19 | 1 | | CSharp7.cs:96:18:96:43 | (..., ...) | CSharp7.cs:96:18:96:43 | (Int32,(String,Int32)) | 1 | CSharp7.cs:96:22:96:42 | (..., ...) | | CSharp7.cs:96:22:96:42 | (..., ...) | file://:0:0:0:0 | (String,Int32) | 0 | CSharp7.cs:96:23:96:38 | "TupleExprNode2" | @@ -82,11 +82,11 @@ | CSharp7.cs:223:9:223:18 | (..., ...) | CSharp7.cs:213:5:213:17 | (Int32,Double) | 1 | CSharp7.cs:223:17:223:17 | _ | | CSharp7.cs:224:9:224:18 | (..., ...) | CSharp7.cs:213:5:213:17 | (Int32,Double) | 0 | CSharp7.cs:224:10:224:10 | _ | | CSharp7.cs:224:9:224:18 | (..., ...) | CSharp7.cs:213:5:213:17 | (Int32,Double) | 1 | CSharp7.cs:224:17:224:17 | Double y | -| CSharp7.cs:283:40:283:61 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 0 | CSharp7.cs:283:41:283:48 | access to property Key | -| CSharp7.cs:283:40:283:61 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 1 | CSharp7.cs:283:51:283:60 | access to property Value | -| CSharp7.cs:285:18:285:34 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 0 | CSharp7.cs:285:23:285:23 | Int32 a | -| CSharp7.cs:285:18:285:34 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 1 | CSharp7.cs:285:33:285:33 | String b | -| CSharp7.cs:287:18:287:31 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 0 | CSharp7.cs:287:23:287:23 | Int32 a | -| CSharp7.cs:287:18:287:31 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 1 | CSharp7.cs:287:30:287:30 | String b | -| CSharp7.cs:289:18:289:27 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 0 | CSharp7.cs:289:23:289:23 | Int32 a | -| CSharp7.cs:289:18:289:27 | (..., ...) | file://:0:0:0:0 | (Int32,String) | 1 | CSharp7.cs:289:26:289:26 | String b | +| CSharp7.cs:283:40:283:61 | (..., ...) | CSharp7.cs:95:18:95:38 | (Int32,String) | 0 | CSharp7.cs:283:41:283:48 | access to property Key | +| CSharp7.cs:283:40:283:61 | (..., ...) | CSharp7.cs:95:18:95:38 | (Int32,String) | 1 | CSharp7.cs:283:51:283:60 | access to property Value | +| CSharp7.cs:285:18:285:34 | (..., ...) | CSharp7.cs:95:18:95:38 | (Int32,String) | 0 | CSharp7.cs:285:23:285:23 | Int32 a | +| CSharp7.cs:285:18:285:34 | (..., ...) | CSharp7.cs:95:18:95:38 | (Int32,String) | 1 | CSharp7.cs:285:33:285:33 | String b | +| CSharp7.cs:287:18:287:31 | (..., ...) | CSharp7.cs:95:18:95:38 | (Int32,String) | 0 | CSharp7.cs:287:23:287:23 | Int32 a | +| CSharp7.cs:287:18:287:31 | (..., ...) | CSharp7.cs:95:18:95:38 | (Int32,String) | 1 | CSharp7.cs:287:30:287:30 | String b | +| CSharp7.cs:289:18:289:27 | (..., ...) | CSharp7.cs:95:18:95:38 | (Int32,String) | 0 | CSharp7.cs:289:23:289:23 | Int32 a | +| CSharp7.cs:289:18:289:27 | (..., ...) | CSharp7.cs:95:18:95:38 | (Int32,String) | 1 | CSharp7.cs:289:26:289:26 | String b | diff --git a/csharp/ql/test/library-tests/csharp7/TupleTypes.expected b/csharp/ql/test/library-tests/csharp7/TupleTypes.expected index 55c27e756f4..d958ad60e4d 100644 --- a/csharp/ql/test/library-tests/csharp7/TupleTypes.expected +++ b/csharp/ql/test/library-tests/csharp7/TupleTypes.expected @@ -1,10 +1,13 @@ | (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:96:22:96:42 | Item2 | +| (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 | 0 | CSharp7.cs:101:19:101:38 | 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 |