Skip to content

Commit e6aebd9

Browse files
authored
Merge pull request #11814 from michaelnebel/csharp/genericattributes
C# 11: Generic attributes
2 parents 14468b6 + 4c94adb commit e6aebd9

14 files changed

+432
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: majorAnalysis
3+
---
4+
* Added library support for generic attributes (also for CIL extracted attributes).
5+
* `cil.ConstructedType::getName` was changed to include printing of the type arguments.

csharp/ql/lib/semmle/code/cil/Attribute.qll

+16
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,19 @@ class Attribute extends Element, @cil_attribute {
2727

2828
override CS::Location getLocation() { result = getDeclaration().getLocation() }
2929
}
30+
31+
/** A generic attribute to a declaration. */
32+
class GenericAttribute extends Attribute {
33+
private ConstructedType type;
34+
35+
GenericAttribute() { type = this.getType() }
36+
37+
/** Gets the total number of type arguments. */
38+
int getNumberOfTypeArguments() { result = count(int i | cil_type_argument(type, i, _)) }
39+
40+
/** Gets the `i`th type argument, if any. */
41+
Type getTypeArgument(int i) { result = type.getTypeArgument(i) }
42+
43+
/** Get a type argument. */
44+
Type getATypeArgument() { result = this.getTypeArgument(_) }
45+
}

csharp/ql/lib/semmle/code/cil/Generics.qll

+10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ class ConstructedGeneric extends Generic, DotNet::ConstructedGeneric {
2828
final override Type getTypeArgument(int n) { cil_type_argument(this, n, result) }
2929
}
3030

31+
/** Gets the concatenation of the `getName()` of type arguments. */
32+
language[monotonicAggregates]
33+
private string getTypeArgumentsNames(ConstructedGeneric cg) {
34+
result = strictconcat(Type t, int i | t = cg.getTypeArgument(i) | t.getName(), "," order by i)
35+
}
36+
3137
/** An unbound generic type. */
3238
class UnboundGenericType extends UnboundGeneric, Type { }
3339

@@ -41,6 +47,10 @@ class ConstructedType extends ConstructedGeneric, Type {
4147
override predicate isInterface() { this.getUnboundType().isInterface() }
4248

4349
override predicate isClass() { this.getUnboundType().isClass() }
50+
51+
final override string getName() {
52+
result = this.getUndecoratedName() + "<" + getTypeArgumentsNames(this) + ">"
53+
}
4454
}
4555

4656
/** A constructed generic method. */

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

+75-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,14 @@ class Attributable extends @attributable {
3737
}
3838

3939
private string getAttributeName(Attribute a) {
40-
exists(string type | type = a.getType().getName() |
41-
if type.matches("%Attribute") then result = type.prefix(type.length() - 9) else result = type
40+
exists(string type, string pattern |
41+
type = a.getType().getName() and pattern = "(.*)Attribute(<.*>)?"
42+
|
43+
type.regexpMatch(pattern) and
44+
result = concat(int i | i = [1, 2] | type.regexpCapture(pattern, i) order by i)
45+
or
46+
not type.regexpMatch(pattern) and
47+
result = type
4248
)
4349
}
4450

@@ -99,6 +105,31 @@ class Attribute extends TopLevelExprParent, @attribute {
99105
override string getAPrimaryQlClass() { result = "Attribute" }
100106
}
101107

108+
/**
109+
* A generic attribute, for example `[...]` on line 1 in
110+
*
111+
* ```csharp
112+
* [MyGenericAttribute<int>(0)]
113+
* public void SomeMethod(string s) { }
114+
* ```
115+
*/
116+
class GenericAttribute extends Attribute {
117+
private ConstructedClass type;
118+
119+
GenericAttribute() { type = this.getType() }
120+
121+
/** Gets the total number of type arguments. */
122+
int getNumberOfTypeArguments() { result = count(int i | type_arguments(_, i, type)) }
123+
124+
/** Gets the `i`th type argument, if any. */
125+
Type getTypeArgument(int i) { result = type.getTypeArgument(i) }
126+
127+
/** Get a type argument. */
128+
Type getATypeArgument() { result = this.getTypeArgument(_) }
129+
130+
override string getAPrimaryQlClass() { result = "GenericAttribute" }
131+
}
132+
102133
/**
103134
* An attribute with default kind, for example `[...]` on line 1 in
104135
* ```csharp
@@ -110,6 +141,17 @@ class DefaultAttribute extends Attribute, @attribute_default {
110141
override string getAPrimaryQlClass() { result = "DefaultAttribute" }
111142
}
112143

144+
/**
145+
* A generic attribute with default kind, for example `[...]` on line 1 in
146+
* ```csharp
147+
* [MyAttribute<string>(0)]
148+
* int SomeMethod() { return 1; }
149+
* ```
150+
*/
151+
class GenericDefaultAttribute extends GenericAttribute, DefaultAttribute {
152+
override string getAPrimaryQlClass() { result = "GenericDefaultAttribute" }
153+
}
154+
113155
/**
114156
* An attribute with return kind, for example `[...]` on line 1 in
115157
* ```csharp
@@ -123,6 +165,17 @@ class ReturnAttribute extends Attribute, @attribute_return {
123165
override string getAPrimaryQlClass() { result = "ReturnAttribute" }
124166
}
125167

168+
/**
169+
* A generic attribute with return kind, for example `[...]` on line 1 in
170+
* ```csharp
171+
* [return: MyAttribute<object>(0)]
172+
* int SomeMethod() { return 1; }
173+
* ```
174+
*/
175+
class GenericReturnAttribute extends GenericAttribute, ReturnAttribute {
176+
override string getAPrimaryQlClass() { result = "GenericReturnAttribute" }
177+
}
178+
126179
/**
127180
* An attribute with assembly kind, for example `[...]` on line 1 in
128181
* ```csharp
@@ -135,6 +188,16 @@ class AssemblyAttribute extends Attribute, @attribute_assembly {
135188
override string getAPrimaryQlClass() { result = "AssemblyAttribute" }
136189
}
137190

191+
/**
192+
* A generic attribute with assembly kind, for example `[...]` on line 1 in
193+
* ```csharp
194+
* [assembly: MyAttribute<string>(0)]
195+
* ```
196+
*/
197+
class GenericAssemblyAttribute extends GenericAttribute, AssemblyAttribute {
198+
override string getAPrimaryQlClass() { result = "GenericAssemblyAttribute" }
199+
}
200+
138201
/**
139202
* An attribute with module kind, for example `[...]` on line 1 in
140203
* ```csharp
@@ -146,3 +209,13 @@ class ModuleAttribute extends Attribute, @attribute_module {
146209

147210
override string getAPrimaryQlClass() { result = "ModuleAttribute" }
148211
}
212+
213+
/**
214+
* A generic attribute with module kind, for example `[...]` on line 1 in
215+
* ```csharp
216+
* [module: MyAttribute<string>(0)]
217+
* ```
218+
*/
219+
class GenericModuleAttribute extends GenericAttribute, ModuleAttribute {
220+
override string getAPrimaryQlClass() { result = "GenericModuleAttribute" }
221+
}

0 commit comments

Comments
 (0)