From 144e9e627110d114523be5c4eb1ca6984ade25e8 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 5 Nov 2020 12:18:14 +0100 Subject: [PATCH 1/2] C#: C#9 Add target typed conditional tests --- .../library-tests/csharp9/PrintAst.expected | 52 +++++++++++++++++++ .../test/library-tests/csharp9/TargetType.cs | 20 +++++++ .../library-tests/csharp9/TargetType.expected | 2 + .../test/library-tests/csharp9/TargetType.ql | 7 +++ 4 files changed, 81 insertions(+) create mode 100644 csharp/ql/test/library-tests/csharp9/TargetType.cs create mode 100644 csharp/ql/test/library-tests/csharp9/TargetType.expected create mode 100644 csharp/ql/test/library-tests/csharp9/TargetType.ql diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index cd5b3a656a7f..0236321d43ba 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -335,6 +335,58 @@ ParenthesizedPattern.cs: # 27| 0: [TypeAccessPatternExpr] access to type String # 27| 0: [TypeMention] string # 27| 2: [IntLiteral] 5 +TargetType.cs: +# 5| [Class] TargetType +# 7| 5: [Method] M2 +# 7| -1: [TypeMention] Void +# 8| 4: [BlockStmt] {...} +# 9| 0: [LocalVariableDeclStmt] ... ...; +# 9| 0: [LocalVariableDeclAndInitExpr] Random rand = ... +# 9| -1: [TypeMention] Random +# 9| 0: [LocalVariableAccess] access to local variable rand +# 9| 1: [ObjectCreation] object creation of type Random +# 9| 0: [TypeMention] Random +# 10| 1: [LocalVariableDeclStmt] ... ...; +# 10| 0: [LocalVariableDeclAndInitExpr] Boolean condition = ... +# 10| -1: [TypeMention] bool +# 10| 0: [LocalVariableAccess] access to local variable condition +# 10| 1: [GTExpr] ... > ... +# 10| 0: [MethodCall] call to method NextDouble +# 10| -1: [LocalVariableAccess] access to local variable rand +# 10| 1: [DoubleLiteral] 0.5 +# 12| 2: [LocalVariableDeclStmt] ... ...; +# 12| 0: [LocalVariableDeclAndInitExpr] Nullable x = ... +# 12| -1: [TypeMention] int? +# 12| 1: [TypeMention] int +# 12| 0: [LocalVariableAccess] access to local variable x +# 12| 1: [ConditionalExpr] ... ? ... : ... +# 12| 0: [LocalVariableAccess] access to local variable condition +# 13| 1: [CastExpr] (...) ... +# 13| 1: [IntLiteral] 12 +# 14| 2: [NullLiteral] null +# 16| 3: [LocalVariableDeclStmt] ... ...; +# 16| 0: [LocalVariableDeclAndInitExpr] IEnumerable xs = ... +# 16| -1: [TypeMention] IEnumerable +# 16| 1: [TypeMention] int +# 16| 0: [LocalVariableAccess] access to local variable xs +# 16| 1: [ConditionalExpr] ... ? ... : ... +# 16| 0: [IsExpr] ... is ... +# 16| 0: [LocalVariableAccess] access to local variable x +# 16| 1: [ConstantPatternExpr,NullLiteral] null +# 17| 1: [ObjectCreation] object creation of type List +# 17| -2: [TypeMention] List +# 17| 1: [TypeMention] int +# 17| -1: [CollectionInitializer] { ..., ... } +# 17| 0: [ElementInitializer] call to method Add +# 17| 0: [IntLiteral] 0 +# 17| 1: [ElementInitializer] call to method Add +# 17| 0: [IntLiteral] 1 +# 18| 2: [ArrayCreation] array creation of type Int32[] +# 18| -2: [TypeMention] Int32[] +# 18| 1: [TypeMention] int +# 18| -1: [ArrayInitializer] { ..., ... } +# 18| 0: [IntLiteral] 2 +# 18| 1: [IntLiteral] 3 TypeParameterNullability.cs: # 1| [Interface] I1 # 3| [Class] A2 diff --git a/csharp/ql/test/library-tests/csharp9/TargetType.cs b/csharp/ql/test/library-tests/csharp9/TargetType.cs new file mode 100644 index 000000000000..758d915ec553 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/TargetType.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +public class TargetType +{ + public void M2() + { + var rand = new Random(); + var condition = rand.NextDouble() > 0.5; + + int? x = condition + ? 12 + : null; + + IEnumerable xs = x is null + ? new List() { 0, 1 } + : new int[] { 2, 3 }; + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/TargetType.expected b/csharp/ql/test/library-tests/csharp9/TargetType.expected new file mode 100644 index 000000000000..20b12551518e --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/TargetType.expected @@ -0,0 +1,2 @@ +| TargetType.cs:12:18:14:18 | ... ? ... : ... | int? | int? | null | +| TargetType.cs:16:31:18:32 | ... ? ... : ... | IEnumerable | List | Int32[] | diff --git a/csharp/ql/test/library-tests/csharp9/TargetType.ql b/csharp/ql/test/library-tests/csharp9/TargetType.ql new file mode 100644 index 000000000000..9d629a36a672 --- /dev/null +++ b/csharp/ql/test/library-tests/csharp9/TargetType.ql @@ -0,0 +1,7 @@ +import csharp + +query predicate conditional(ConditionalExpr expr, string t, string t1, string t2) { + expr.getType().toStringWithTypes() = t and + expr.getThen().getType().toStringWithTypes() = t1 and + expr.getElse().getType().toStringWithTypes() = t2 +} From 548f276e1f4d568c545496adc6dacd4b4a4ee538 Mon Sep 17 00:00:00 2001 From: Tamas Vajk Date: Thu, 26 Nov 2020 12:15:21 +0100 Subject: [PATCH 2/2] Add more tests --- .../library-tests/csharp9/PrintAst.expected | 143 ++++++++++++++---- .../test/library-tests/csharp9/TargetType.cs | 25 ++- .../library-tests/csharp9/TargetType.expected | 16 +- .../test/library-tests/csharp9/TargetType.ql | 16 ++ 4 files changed, 168 insertions(+), 32 deletions(-) diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected index 0236321d43ba..42a0fad8d144 100644 --- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected @@ -355,38 +355,125 @@ TargetType.cs: # 10| -1: [LocalVariableAccess] access to local variable rand # 10| 1: [DoubleLiteral] 0.5 # 12| 2: [LocalVariableDeclStmt] ... ...; -# 12| 0: [LocalVariableDeclAndInitExpr] Nullable x = ... +# 12| 0: [LocalVariableDeclAndInitExpr] Nullable x0 = ... # 12| -1: [TypeMention] int? # 12| 1: [TypeMention] int -# 12| 0: [LocalVariableAccess] access to local variable x -# 12| 1: [ConditionalExpr] ... ? ... : ... -# 12| 0: [LocalVariableAccess] access to local variable condition -# 13| 1: [CastExpr] (...) ... -# 13| 1: [IntLiteral] 12 -# 14| 2: [NullLiteral] null -# 16| 3: [LocalVariableDeclStmt] ... ...; -# 16| 0: [LocalVariableDeclAndInitExpr] IEnumerable xs = ... -# 16| -1: [TypeMention] IEnumerable +# 12| 0: [LocalVariableAccess] access to local variable x0 +# 12| 1: [CastExpr] (...) ... +# 12| 1: [IntLiteral] 12 +# 13| 3: [ExprStmt] ...; +# 13| 0: [AssignExpr] ... = ... +# 13| 0: [LocalVariableAccess] access to local variable x0 +# 13| 1: [CastExpr] (...) ... +# 13| 1: [IntLiteral] 13 +# 14| 4: [LocalVariableDeclStmt] ... ...; +# 14| 0: [LocalVariableDeclAndInitExpr] Nullable x1 = ... +# 14| -1: [TypeMention] int? +# 14| 1: [TypeMention] int +# 14| 0: [LocalVariableAccess] access to local variable x1 +# 14| 1: [NullLiteral] null +# 16| 5: [LocalVariableDeclStmt] ... ...; +# 16| 0: [LocalVariableDeclAndInitExpr] Nullable x2 = ... +# 16| -1: [TypeMention] int? # 16| 1: [TypeMention] int -# 16| 0: [LocalVariableAccess] access to local variable xs +# 16| 0: [LocalVariableAccess] access to local variable x2 # 16| 1: [ConditionalExpr] ... ? ... : ... -# 16| 0: [IsExpr] ... is ... -# 16| 0: [LocalVariableAccess] access to local variable x -# 16| 1: [ConstantPatternExpr,NullLiteral] null -# 17| 1: [ObjectCreation] object creation of type List -# 17| -2: [TypeMention] List -# 17| 1: [TypeMention] int -# 17| -1: [CollectionInitializer] { ..., ... } -# 17| 0: [ElementInitializer] call to method Add -# 17| 0: [IntLiteral] 0 -# 17| 1: [ElementInitializer] call to method Add -# 17| 0: [IntLiteral] 1 -# 18| 2: [ArrayCreation] array creation of type Int32[] -# 18| -2: [TypeMention] Int32[] -# 18| 1: [TypeMention] int -# 18| -1: [ArrayInitializer] { ..., ... } -# 18| 0: [IntLiteral] 2 -# 18| 1: [IntLiteral] 3 +# 16| 0: [LocalVariableAccess] access to local variable condition +# 17| 1: [CastExpr] (...) ... +# 17| 1: [IntLiteral] 12 +# 18| 2: [NullLiteral] null +# 20| 6: [LocalVariableDeclStmt] ... ...; +# 20| 0: [LocalVariableDeclAndInitExpr] Nullable x3 = ... +# 20| -1: [TypeMention] int? +# 20| 1: [TypeMention] int +# 20| 0: [LocalVariableAccess] access to local variable x3 +# 20| 1: [ConditionalExpr] ... ? ... : ... +# 20| 0: [LocalVariableAccess] access to local variable condition +# 21| 1: [CastExpr] (...) ... +# 21| 0: [TypeAccess] access to type Nullable +# 21| 0: [TypeMention] int? +# 21| 1: [TypeMention] int +# 21| 1: [IntLiteral] 12 +# 22| 2: [NullLiteral] null +# 24| 7: [LocalVariableDeclStmt] ... ...; +# 24| 0: [LocalVariableDeclAndInitExpr] Nullable x4 = ... +# 24| -1: [TypeMention] int? +# 24| 1: [TypeMention] int +# 24| 0: [LocalVariableAccess] access to local variable x4 +# 24| 1: [ConditionalExpr] ... ? ... : ... +# 24| 0: [LocalVariableAccess] access to local variable condition +# 25| 1: [CastExpr] (...) ... +# 25| 1: [IntLiteral] 12 +# 26| 2: [CastExpr] (...) ... +# 26| 0: [TypeAccess] access to type Nullable +# 26| 0: [TypeMention] int? +# 26| 1: [TypeMention] int +# 26| 1: [NullLiteral] null +# 28| 8: [LocalVariableDeclStmt] ... ...; +# 28| 0: [LocalVariableDeclAndInitExpr] IEnumerable xs0 = ... +# 28| -1: [TypeMention] IEnumerable +# 28| 1: [TypeMention] int +# 28| 0: [LocalVariableAccess] access to local variable xs0 +# 28| 1: [ObjectCreation] object creation of type List +# 28| -2: [TypeMention] List +# 28| 1: [TypeMention] int +# 28| -1: [CollectionInitializer] { ..., ... } +# 28| 0: [ElementInitializer] call to method Add +# 28| 0: [IntLiteral] 0 +# 28| 1: [ElementInitializer] call to method Add +# 28| 0: [IntLiteral] 1 +# 29| 9: [LocalVariableDeclStmt] ... ...; +# 29| 0: [LocalVariableDeclAndInitExpr] IEnumerable xs1 = ... +# 29| -1: [TypeMention] IEnumerable +# 29| 1: [TypeMention] int +# 29| 0: [LocalVariableAccess] access to local variable xs1 +# 29| 1: [ArrayCreation] array creation of type Int32[] +# 29| -2: [TypeMention] Int32[] +# 29| 1: [TypeMention] int +# 29| -1: [ArrayInitializer] { ..., ... } +# 29| 0: [IntLiteral] 2 +# 29| 1: [IntLiteral] 3 +# 31| 10: [LocalVariableDeclStmt] ... ...; +# 31| 0: [LocalVariableDeclAndInitExpr] IEnumerable xs2 = ... +# 31| -1: [TypeMention] IEnumerable +# 31| 1: [TypeMention] int +# 31| 0: [LocalVariableAccess] access to local variable xs2 +# 31| 1: [ConditionalExpr] ... ? ... : ... +# 31| 0: [IsExpr] ... is ... +# 31| 0: [LocalVariableAccess] access to local variable x2 +# 31| 1: [ConstantPatternExpr,NullLiteral] null +# 32| 1: [ObjectCreation] object creation of type List +# 32| -2: [TypeMention] List +# 32| 1: [TypeMention] int +# 32| -1: [CollectionInitializer] { ..., ... } +# 32| 0: [ElementInitializer] call to method Add +# 32| 0: [IntLiteral] 0 +# 32| 1: [ElementInitializer] call to method Add +# 32| 0: [IntLiteral] 1 +# 33| 2: [ArrayCreation] array creation of type Int32[] +# 33| -2: [TypeMention] Int32[] +# 33| 1: [TypeMention] int +# 33| -1: [ArrayInitializer] { ..., ... } +# 33| 0: [IntLiteral] 2 +# 33| 1: [IntLiteral] 3 +# 35| 11: [LocalVariableDeclStmt] ... ...; +# 35| 0: [LocalVariableDeclAndInitExpr] Nullable c = ... +# 35| -1: [TypeMention] int? +# 35| 1: [TypeMention] int +# 35| 0: [LocalVariableAccess] access to local variable c +# 35| 1: [CastExpr] (...) ... +# 35| 1: [ConditionalExpr] ... ? ... : ... +# 35| 0: [LocalVariableAccess] access to local variable condition +# 36| 1: [OperatorCall] call to operator implicit conversion +# 36| 0: [ObjectCreation] object creation of type TargetType +# 36| 0: [TypeMention] TargetType +# 37| 2: [IntLiteral] 12 +# 40| 6: [ImplicitConversionOperator] implicit conversion +# 40| -1: [TypeMention] int +#-----| 2: (Parameters) +# 40| 0: [Parameter] d +# 40| -1: [TypeMention] TargetType +# 40| 4: [IntLiteral] 0 TypeParameterNullability.cs: # 1| [Interface] I1 # 3| [Class] A2 diff --git a/csharp/ql/test/library-tests/csharp9/TargetType.cs b/csharp/ql/test/library-tests/csharp9/TargetType.cs index 758d915ec553..96a236ac3a81 100644 --- a/csharp/ql/test/library-tests/csharp9/TargetType.cs +++ b/csharp/ql/test/library-tests/csharp9/TargetType.cs @@ -9,12 +9,33 @@ public void M2() var rand = new Random(); var condition = rand.NextDouble() > 0.5; - int? x = condition + int? x0 = 12; + x0 = 13; + int? x1 = null; + + int? x2 = condition ? 12 : null; - IEnumerable xs = x is null + int? x3 = condition + ? (int?)12 + : null; + + int? x4 = condition + ? 12 + : (int?)null; + + IEnumerable xs0 = new List() { 0, 1 }; + IEnumerable xs1 = new int[] { 2, 3 }; + + IEnumerable xs2 = x2 is null ? new List() { 0, 1 } : new int[] { 2, 3 }; + + int? c = condition + ? new TargetType() + : 12; } + + public static implicit operator int(TargetType d) => 0; } \ No newline at end of file diff --git a/csharp/ql/test/library-tests/csharp9/TargetType.expected b/csharp/ql/test/library-tests/csharp9/TargetType.expected index 20b12551518e..52bb8406125a 100644 --- a/csharp/ql/test/library-tests/csharp9/TargetType.expected +++ b/csharp/ql/test/library-tests/csharp9/TargetType.expected @@ -1,2 +1,14 @@ -| TargetType.cs:12:18:14:18 | ... ? ... : ... | int? | int? | null | -| TargetType.cs:16:31:18:32 | ... ? ... : ... | IEnumerable | List | Int32[] | +conditional +| TargetType.cs:16:19:18:18 | ... ? ... : ... | int? | int? | null | +| TargetType.cs:20:19:22:18 | ... ? ... : ... | int? | int? | null | +| TargetType.cs:24:19:26:24 | ... ? ... : ... | int? | int? | int? | +| TargetType.cs:31:32:33:32 | ... ? ... : ... | IEnumerable | List | Int32[] | +| TargetType.cs:35:18:37:16 | ... ? ... : ... | int | int | int | +implicitCasts +| TargetType.cs:12:19:12:20 | (...) ... | int? | int | +| TargetType.cs:13:14:13:15 | (...) ... | int? | int | +| TargetType.cs:17:15:17:16 | (...) ... | int? | int | +| TargetType.cs:25:15:25:16 | (...) ... | int? | int | +| TargetType.cs:35:18:37:16 | (...) ... | int? | int | +implicitConversions +| TargetType.cs:36:15:36:30 | call to operator implicit conversion | int | TargetType | diff --git a/csharp/ql/test/library-tests/csharp9/TargetType.ql b/csharp/ql/test/library-tests/csharp9/TargetType.ql index 9d629a36a672..95027ece89fa 100644 --- a/csharp/ql/test/library-tests/csharp9/TargetType.ql +++ b/csharp/ql/test/library-tests/csharp9/TargetType.ql @@ -5,3 +5,19 @@ query predicate conditional(ConditionalExpr expr, string t, string t1, string t2 expr.getThen().getType().toStringWithTypes() = t1 and expr.getElse().getType().toStringWithTypes() = t2 } + +query predicate implicitCasts(CastExpr expr, string type, string childType) { + expr.getFile().getStem() = "TargetType" and + expr.fromSource() and + not exists(expr.getTypeAccess()) and + type = expr.getType().toStringWithTypes() and + childType = expr.getExpr().getType().toStringWithTypes() +} + +query predicate implicitConversions(OperatorCall opCall, string type, string childType) { + opCall.getFile().getStem() = "TargetType" and + opCall.fromSource() and + opCall.getTarget().getFunctionName() = "op_Implicit" and + opCall.getTarget().getReturnType().toStringWithTypes() = type and + opCall.getAnArgument().getType().toStringWithTypes() = childType +}