Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 225c22c

Browse files
authored
Merge pull request #1171 from hvitved/csharp/attributes-named-args
Approved by calumgrant
2 parents 8012dac + 664aa8d commit 225c22c

9 files changed

Lines changed: 121 additions & 14 deletions

File tree

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Improvements to C# analysis
2+
3+
## Changes to existing queries
4+
5+
| **Query** | **Expected impact** | **Change** |
6+
|------------------------------|------------------------|-----------------------------------|
7+
8+
9+
## Changes to code extraction
10+
11+
* Named attribute arguments are now extracted.
12+
13+
## Changes to QL libraries
14+
15+
* The class `Attribute` has two new predicates: `getConstructorArgument()` and `getNamedArgument()`. The first predicate returns arguments to the underlying constructor call and the latter returns named arguments for initializing fields and properties.
16+
17+
## Changes to autobuilder

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

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,12 @@ void ExtractAttribute(AttributeSyntax syntax, ITypeSymbol attributeClass, IEntit
5151
int child = 0;
5252
foreach (var arg in syntax.ArgumentList.Arguments)
5353
{
54-
Expression.Create(cx, arg.Expression, this, child++);
54+
var expr = Expression.Create(cx, arg.Expression, this, child++);
55+
if (!(arg.NameEquals is null))
56+
{
57+
cx.Emit(Tuples.expr_argument_name(expr, arg.NameEquals.Name.Identifier.Text));
58+
}
5559
}
56-
// !! Handle named arguments
5760
});
5861
}
5962
}
@@ -66,14 +69,6 @@ public static void ExtractAttributes(Context cx, ISymbol symbol, IEntity entity)
6669
}
6770
}
6871

69-
public static void ExtractAttributes(Context cx, IEnumerable<AttributeListSyntax> attributes, IEntity entity)
70-
{
71-
foreach (var attributeSyntax in attributes.SelectMany(l => l.Attributes))
72-
{
73-
new Attribute(cx, attributeSyntax, entity);
74-
}
75-
}
76-
7772
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel;
7873
}
7974
}

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

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ class Attributable extends @attributable {
2828
predicate hasLocationInfo(
2929
string filepath, int startline, int startcolumn, int endline, int endcolumn
3030
) {
31-
this.(Element).getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
31+
this
32+
.(Element)
33+
.getLocation()
34+
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
3235
}
3336
}
3437

@@ -51,9 +54,37 @@ class Attribute extends TopLevelExprParent, @attribute {
5154
/** Gets the element that this attribute is attached to. */
5255
Attributable getTarget() { attributes(this, _, result) }
5356

54-
/** Gets the `i`th argument of this attribute. */
57+
/**
58+
* Gets the `i`th argument of this attribute. This includes both constructor
59+
* arguments and named arguments.
60+
*/
5561
Expr getArgument(int i) { result = this.getChildExpr(i) }
5662

63+
/**
64+
* Gets the `i`th constructor argument of this attribute. For example, only
65+
* `true` is a constructor argument in
66+
*
67+
* ```
68+
* MyAttribute[true, Foo = 0]
69+
* ```
70+
*/
71+
Expr getConstructorArgument(int i) {
72+
result = this.getArgument(i) and not exists(result.getExplicitArgumentName())
73+
}
74+
75+
/**
76+
* Gets the named argument `name` of this attribute. For example, only
77+
* `0` is a named argument in
78+
*
79+
* ```
80+
* MyAttribute[true, Foo = 0]
81+
* ```
82+
*/
83+
Expr getNamedArgument(string name) {
84+
result = this.getArgument(_) and
85+
result.getExplicitArgumentName() = name
86+
}
87+
5788
override Location getALocation() { attribute_location(this, result) }
5889

5990
override string toString() {

csharp/ql/test/library-tests/arguments/argumentName.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
| arguments.cs:39:27:39:27 | 0 | o |
88
| arguments.cs:40:18:40:35 | array creation of type Int32[] | args |
99
| arguments.cs:40:41:40:41 | 0 | o |
10+
| arguments.cs:68:28:68:29 | "" | y |
11+
| arguments.cs:68:36:68:36 | 0 | x |

csharp/ql/test/library-tests/arguments/arguments.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,17 @@ void f5()
6161
var tuple = (13, 14);
6262
(Prop, this[15, 16]) = tuple;
6363
}
64+
65+
[MyAttribute(false)]
66+
void f6() { }
67+
68+
[MyAttribute(true, y = "", x = 0)]
69+
void f7() { }
70+
}
71+
72+
class MyAttribute : Attribute
73+
{
74+
public int x;
75+
public string y { get; set; }
76+
public MyAttribute(bool b) { }
6477
}

csharp/ql/test/library-tests/attributes/AttributeArguments.expected

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
arguments
12
| attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | 0 | attributes.cs:10:26:10:45 | "C# attributes test" |
23
| attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | 0 | attributes.cs:11:32:11:56 | "A test of C# attributes" |
34
| attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | 0 | attributes.cs:12:34:12:35 | "" |
@@ -12,3 +13,27 @@
1213
| attributes.cs:38:12:38:30 | [AssemblyFileVersion(...)] | 0 | attributes.cs:38:32:38:40 | "1.0.0.0" |
1314
| attributes.cs:40:2:40:22 | [AttributeUsage(...)] | 0 | attributes.cs:40:24:40:50 | access to constant All |
1415
| attributes.cs:43:6:43:16 | [Conditional(...)] | 0 | attributes.cs:43:18:43:25 | "DEBUG2" |
16+
| attributes.cs:51:6:51:16 | [My(...)] | 0 | attributes.cs:51:18:51:22 | false |
17+
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:21 | true |
18+
| attributes.cs:54:6:54:16 | [My(...)] | 1 | attributes.cs:54:28:54:29 | "" |
19+
| attributes.cs:54:6:54:16 | [My(...)] | 2 | attributes.cs:54:36:54:36 | 0 |
20+
constructorArguments
21+
| attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | 0 | attributes.cs:10:26:10:45 | "C# attributes test" |
22+
| attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | 0 | attributes.cs:11:32:11:56 | "A test of C# attributes" |
23+
| attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | 0 | attributes.cs:12:34:12:35 | "" |
24+
| attributes.cs:13:12:13:26 | [AssemblyCompany(...)] | 0 | attributes.cs:13:28:13:39 | "Semmle Plc" |
25+
| attributes.cs:14:12:14:26 | [AssemblyProduct(...)] | 0 | attributes.cs:14:28:14:34 | "Odasa" |
26+
| attributes.cs:15:12:15:28 | [AssemblyCopyright(...)] | 0 | attributes.cs:15:30:15:54 | "Copyright \ufffd Semmle 2018" |
27+
| attributes.cs:16:12:16:28 | [AssemblyTrademark(...)] | 0 | attributes.cs:16:30:16:31 | "" |
28+
| attributes.cs:17:12:17:26 | [AssemblyCulture(...)] | 0 | attributes.cs:17:28:17:29 | "" |
29+
| attributes.cs:22:12:22:21 | [ComVisible(...)] | 0 | attributes.cs:22:23:22:27 | false |
30+
| attributes.cs:25:12:25:15 | [Guid(...)] | 0 | attributes.cs:25:17:25:54 | "2f70fdd6-14aa-4850-b053-d547adb1f476" |
31+
| attributes.cs:37:12:37:26 | [AssemblyVersion(...)] | 0 | attributes.cs:37:28:37:36 | "1.0.0.0" |
32+
| attributes.cs:38:12:38:30 | [AssemblyFileVersion(...)] | 0 | attributes.cs:38:32:38:40 | "1.0.0.0" |
33+
| attributes.cs:40:2:40:22 | [AttributeUsage(...)] | 0 | attributes.cs:40:24:40:50 | access to constant All |
34+
| attributes.cs:43:6:43:16 | [Conditional(...)] | 0 | attributes.cs:43:18:43:25 | "DEBUG2" |
35+
| attributes.cs:51:6:51:16 | [My(...)] | 0 | attributes.cs:51:18:51:22 | false |
36+
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:21 | true |
37+
namedArguments
38+
| attributes.cs:54:6:54:16 | [My(...)] | x | attributes.cs:54:36:54:36 | 0 |
39+
| attributes.cs:54:6:54:16 | [My(...)] | y | attributes.cs:54:28:54:29 | "" |
Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,13 @@
11
import csharp
22

3-
from Attribute attribute, int index
4-
select attribute, index, attribute.getArgument(index)
3+
query predicate arguments(Attribute attribute, int index, Expr e) {
4+
e = attribute.getArgument(index)
5+
}
6+
7+
query predicate constructorArguments(Attribute attribute, int index, Expr e) {
8+
e = attribute.getConstructorArgument(index)
9+
}
10+
11+
query predicate namedArguments(Attribute attribute, string name, Expr e) {
12+
e = attribute.getNamedArgument(name)
13+
}

csharp/ql/test/library-tests/attributes/AttributeElements.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
| attributes.cs:41:7:41:9 | Foo | attributes.cs:40:2:40:22 | [AttributeUsage(...)] | System.AttributeUsageAttribute |
22
| attributes.cs:44:17:44:19 | foo | attributes.cs:43:6:43:16 | [Conditional(...)] | System.Diagnostics.ConditionalAttribute |
33
| attributes.cs:49:23:49:23 | x | attributes.cs:49:14:49:16 | [Foo(...)] | Foo |
4+
| attributes.cs:52:10:52:11 | M1 | attributes.cs:51:6:51:16 | [My(...)] | MyAttribute |
5+
| attributes.cs:55:10:55:11 | M2 | attributes.cs:54:6:54:16 | [My(...)] | MyAttribute |
46
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | System.Reflection.AssemblyTitleAttribute |
57
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | System.Reflection.AssemblyDescriptionAttribute |
68
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | System.Reflection.AssemblyConfigurationAttribute |

csharp/ql/test/library-tests/attributes/attributes.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,17 @@ static void foo() { }
4747
class Bar
4848
{
4949
int inc([Foo] int x) { return x + 1; }
50+
51+
[MyAttribute(false)]
52+
void M1() { }
53+
54+
[MyAttribute(true, y = "", x = 0)]
55+
void M2() { }
56+
}
57+
58+
class MyAttribute : Attribute
59+
{
60+
public int x;
61+
public string y { get; set; }
62+
public MyAttribute(bool b) { }
5063
}

0 commit comments

Comments
 (0)