Skip to content

Commit 2db588f

Browse files
authored
Merge pull request github#12322 from michaelnebel/csharp/operatorexplicitinterface
C# 11: Support for explicit interface implementations of operators.
2 parents 64dad3d + ad5a45e commit 2db588f

File tree

9 files changed

+352
-124
lines changed

9 files changed

+352
-124
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ internal class Conversion : UserOperator
1010
private Conversion(Context cx, IMethodSymbol init)
1111
: base(cx, init) { }
1212

13+
protected override MethodKind ExplicitlyImplementsKind => MethodKind.Conversion;
14+
1315
public static new Conversion Create(Context cx, IMethodSymbol symbol) =>
1416
ConversionFactory.Instance.CreateEntityFromSymbol(cx, symbol);
1517

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,12 @@ public static void NumberOfLines(TextWriter trapFile, ISymbol symbol, IEntity ca
8383
}
8484
}
8585

86+
protected virtual MethodKind ExplicitlyImplementsKind => MethodKind.Ordinary;
87+
8688
public void Overrides(TextWriter trapFile)
8789
{
8890
foreach (var explicitInterface in Symbol.ExplicitInterfaceImplementations
89-
.Where(sym => sym.MethodKind == MethodKind.Ordinary)
91+
.Where(sym => sym.MethodKind == ExplicitlyImplementsKind)
9092
.Select(impl => Type.Create(Context, impl.ContainingType)))
9193
{
9294
trapFile.explicitly_implements(this, explicitInterface.TypeRef);

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ internal class UserOperator : Method
1111
protected UserOperator(Context cx, IMethodSymbol init)
1212
: base(cx, init) { }
1313

14+
protected override MethodKind ExplicitlyImplementsKind => MethodKind.UserDefinedOperator;
15+
1416
public override void Populate(TextWriter trapFile)
1517
{
1618
PopulateMethod(trapFile);
@@ -37,6 +39,7 @@ public override void Populate(TextWriter trapFile)
3739
}
3840

3941
ContainingType.PopulateGenerics();
42+
Overrides(trapFile);
4043
}
4144

4245
public override bool NeedsPopulation => Context.Defines(Symbol) || IsImplicitOperator(out _);
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* C# 11: Support for explicit interface member implementation of operators.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ class Destructor extends DotNet::Destructor, Callable, Member, Attributable, @de
434434
* Either a unary operator (`UnaryOperator`), a binary operator
435435
* (`BinaryOperator`), or a conversion operator (`ConversionOperator`).
436436
*/
437-
class Operator extends Callable, Member, Attributable, @operator {
437+
class Operator extends Callable, Member, Attributable, Overridable, @operator {
438438
/**
439439
* DEPRECATED: use `getFunctionName()` instead.
440440
*

csharp/ql/test/library-tests/csharp11/PrintAst.expected

Lines changed: 254 additions & 110 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/csharp11/StaticInterfaceMembers.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ public interface INumber<T> where T : INumber<T>
44

55
static virtual T operator --(T other) => other;
66

7+
static abstract T operator +(T left, T right);
8+
9+
static virtual T operator -(T left, T right) => left;
10+
11+
static abstract explicit operator int(T n);
12+
13+
static abstract explicit operator short(T n);
14+
15+
static abstract T Inc(T other);
16+
17+
static virtual T Dec(T other) => other;
18+
719
static abstract T Add(T left, T right);
820

921
static virtual T Subtract(T left, T right) => left;
@@ -26,6 +38,22 @@ public Complex() { }
2638
public static Complex operator --(Complex other) =>
2739
new Complex { Real = other.Real - 1.0, Imaginary = other.Imaginary };
2840

41+
static Complex INumber<Complex>.operator +(Complex left, Complex right) =>
42+
new Complex { Real = left.Real + right.Real, Imaginary = left.Imaginary + right.Imaginary };
43+
44+
static Complex INumber<Complex>.operator -(Complex left, Complex right) =>
45+
new Complex { Real = left.Real - right.Real, Imaginary = left.Imaginary - right.Imaginary };
46+
47+
public static explicit operator int(Complex n) => (int)n.Real;
48+
49+
static explicit INumber<Complex>.operator short(Complex n) => (short)n.Real;
50+
51+
static Complex INumber<Complex>.Inc(Complex other) =>
52+
new Complex { Real = other.Real + 1.0, Imaginary = other.Imaginary };
53+
54+
static Complex INumber<Complex>.Dec(Complex other) =>
55+
new Complex { Real = other.Real - 1.0, Imaginary = other.Imaginary };
56+
2957
public static Complex Add(Complex left, Complex right) =>
3058
new Complex { Real = left.Real + right.Real, Imaginary = left.Imaginary + right.Imaginary };
3159

csharp/ql/test/library-tests/csharp11/staticInterfaceMembers.expected

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,55 @@ interfacemembers
55
| INumber<> | StaticInterfaceMembers.cs:5:31:5:32 | -- | public |
66
| INumber<> | StaticInterfaceMembers.cs:5:31:5:32 | -- | static |
77
| INumber<> | StaticInterfaceMembers.cs:5:31:5:32 | -- | virtual |
8-
| INumber<> | StaticInterfaceMembers.cs:7:23:7:25 | Add | abstract |
9-
| INumber<> | StaticInterfaceMembers.cs:7:23:7:25 | Add | public |
10-
| INumber<> | StaticInterfaceMembers.cs:7:23:7:25 | Add | static |
11-
| INumber<> | StaticInterfaceMembers.cs:9:22:9:29 | Subtract | public |
12-
| INumber<> | StaticInterfaceMembers.cs:9:22:9:29 | Subtract | static |
13-
| INumber<> | StaticInterfaceMembers.cs:9:22:9:29 | Subtract | virtual |
14-
| INumber<> | StaticInterfaceMembers.cs:11:14:11:17 | Zero | public |
15-
| INumber<> | StaticInterfaceMembers.cs:11:14:11:17 | Zero | static |
8+
| INumber<> | StaticInterfaceMembers.cs:7:32:7:32 | + | abstract |
9+
| INumber<> | StaticInterfaceMembers.cs:7:32:7:32 | + | public |
10+
| INumber<> | StaticInterfaceMembers.cs:7:32:7:32 | + | static |
11+
| INumber<> | StaticInterfaceMembers.cs:9:31:9:31 | - | public |
12+
| INumber<> | StaticInterfaceMembers.cs:9:31:9:31 | - | static |
13+
| INumber<> | StaticInterfaceMembers.cs:9:31:9:31 | - | virtual |
14+
| INumber<> | StaticInterfaceMembers.cs:11:30:11:37 | explicit conversion | abstract |
15+
| INumber<> | StaticInterfaceMembers.cs:11:30:11:37 | explicit conversion | public |
16+
| INumber<> | StaticInterfaceMembers.cs:11:30:11:37 | explicit conversion | static |
17+
| INumber<> | StaticInterfaceMembers.cs:13:30:13:37 | explicit conversion | abstract |
18+
| INumber<> | StaticInterfaceMembers.cs:13:30:13:37 | explicit conversion | public |
19+
| INumber<> | StaticInterfaceMembers.cs:13:30:13:37 | explicit conversion | static |
20+
| INumber<> | StaticInterfaceMembers.cs:15:23:15:25 | Inc | abstract |
21+
| INumber<> | StaticInterfaceMembers.cs:15:23:15:25 | Inc | public |
22+
| INumber<> | StaticInterfaceMembers.cs:15:23:15:25 | Inc | static |
23+
| INumber<> | StaticInterfaceMembers.cs:17:22:17:24 | Dec | public |
24+
| INumber<> | StaticInterfaceMembers.cs:17:22:17:24 | Dec | static |
25+
| INumber<> | StaticInterfaceMembers.cs:17:22:17:24 | Dec | virtual |
26+
| INumber<> | StaticInterfaceMembers.cs:19:23:19:25 | Add | abstract |
27+
| INumber<> | StaticInterfaceMembers.cs:19:23:19:25 | Add | public |
28+
| INumber<> | StaticInterfaceMembers.cs:19:23:19:25 | Add | static |
29+
| INumber<> | StaticInterfaceMembers.cs:21:22:21:29 | Subtract | public |
30+
| INumber<> | StaticInterfaceMembers.cs:21:22:21:29 | Subtract | static |
31+
| INumber<> | StaticInterfaceMembers.cs:21:22:21:29 | Subtract | virtual |
32+
| INumber<> | StaticInterfaceMembers.cs:23:14:23:17 | Zero | public |
33+
| INumber<> | StaticInterfaceMembers.cs:23:14:23:17 | Zero | static |
1634
implements
17-
| StaticInterfaceMembers.cs:23:36:23:37 | ++ | StaticInterfaceMembers.cs:3:32:3:33 | ++ |
18-
| StaticInterfaceMembers.cs:26:36:26:37 | -- | StaticInterfaceMembers.cs:5:31:5:32 | -- |
19-
| StaticInterfaceMembers.cs:29:27:29:29 | Add | StaticInterfaceMembers.cs:7:23:7:25 | Add |
20-
| StaticInterfaceMembers.cs:32:27:32:34 | Subtract | StaticInterfaceMembers.cs:9:22:9:29 | Subtract |
35+
| StaticInterfaceMembers.cs:35:36:35:37 | ++ | StaticInterfaceMembers.cs:3:32:3:33 | ++ |
36+
| StaticInterfaceMembers.cs:38:36:38:37 | -- | StaticInterfaceMembers.cs:5:31:5:32 | -- |
37+
| StaticInterfaceMembers.cs:41:46:41:46 | + | StaticInterfaceMembers.cs:7:32:7:32 | + |
38+
| StaticInterfaceMembers.cs:44:46:44:46 | - | StaticInterfaceMembers.cs:9:31:9:31 | - |
39+
| StaticInterfaceMembers.cs:47:28:47:35 | explicit conversion | StaticInterfaceMembers.cs:11:30:11:37 | explicit conversion |
40+
| StaticInterfaceMembers.cs:49:38:49:45 | explicit conversion | StaticInterfaceMembers.cs:13:30:13:37 | explicit conversion |
41+
| StaticInterfaceMembers.cs:51:37:51:39 | Inc | StaticInterfaceMembers.cs:15:23:15:25 | Inc |
42+
| StaticInterfaceMembers.cs:54:37:54:39 | Dec | StaticInterfaceMembers.cs:17:22:17:24 | Dec |
43+
| StaticInterfaceMembers.cs:57:27:57:29 | Add | StaticInterfaceMembers.cs:19:23:19:25 | Add |
44+
| StaticInterfaceMembers.cs:60:27:60:34 | Subtract | StaticInterfaceMembers.cs:21:22:21:29 | Subtract |
45+
publicmembers
46+
| StaticInterfaceMembers.cs:28:19:28:22 | Real |
47+
| StaticInterfaceMembers.cs:29:19:29:27 | Imaginary |
48+
| StaticInterfaceMembers.cs:31:12:31:18 | Complex |
49+
| StaticInterfaceMembers.cs:33:27:33:30 | Zero |
50+
| StaticInterfaceMembers.cs:35:36:35:37 | ++ |
51+
| StaticInterfaceMembers.cs:38:36:38:37 | -- |
52+
| StaticInterfaceMembers.cs:41:46:41:46 | + |
53+
| StaticInterfaceMembers.cs:44:46:44:46 | - |
54+
| StaticInterfaceMembers.cs:47:28:47:35 | explicit conversion |
55+
| StaticInterfaceMembers.cs:49:38:49:45 | explicit conversion |
56+
| StaticInterfaceMembers.cs:51:37:51:39 | Inc |
57+
| StaticInterfaceMembers.cs:54:37:54:39 | Dec |
58+
| StaticInterfaceMembers.cs:57:27:57:29 | Add |
59+
| StaticInterfaceMembers.cs:60:27:60:34 | Subtract |

csharp/ql/test/library-tests/csharp11/staticInterfaceMembers.ql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,9 @@ query predicate implements(Overridable o, Virtualizable v) {
1616
v.isStatic() and
1717
v.getAnImplementor() = o
1818
}
19+
20+
query predicate publicmembers(Member m) {
21+
m.getFile().getStem() = "StaticInterfaceMembers" and
22+
m.getDeclaringType().getName() = "Complex" and
23+
m.isPublic()
24+
}

0 commit comments

Comments
 (0)