mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
C#: Handle named attribute arguments
This commit is contained in:
17
change-notes/1.21/analysis-csharp.md
Normal file
17
change-notes/1.21/analysis-csharp.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Improvements to C# analysis
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|------------------------------|------------------------|-----------------------------------|
|
||||
|
||||
|
||||
## Changes to code extraction
|
||||
|
||||
* Named attribute arguments are now extracted.
|
||||
|
||||
## Changes to QL libraries
|
||||
|
||||
* 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.
|
||||
|
||||
## Changes to autobuilder
|
||||
@@ -51,9 +51,12 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
int child = 0;
|
||||
foreach (var arg in syntax.ArgumentList.Arguments)
|
||||
{
|
||||
Expression.Create(cx, arg.Expression, this, child++);
|
||||
var expr = Expression.Create(cx, arg.Expression, this, child++);
|
||||
if (arg.NameEquals != null)
|
||||
{
|
||||
cx.Emit(Tuples.expr_argument_name(expr, arg.NameEquals.Name.Identifier.Text));
|
||||
}
|
||||
}
|
||||
// !! Handle named arguments
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -66,14 +69,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExtractAttributes(Context cx, IEnumerable<AttributeListSyntax> attributes, IEntity entity)
|
||||
{
|
||||
foreach (var attributeSyntax in attributes.SelectMany(l => l.Attributes))
|
||||
{
|
||||
new Attribute(cx, attributeSyntax, entity);
|
||||
}
|
||||
}
|
||||
|
||||
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,10 @@ class Attributable extends @attributable {
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.(Element).getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
this
|
||||
.(Element)
|
||||
.getLocation()
|
||||
.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,9 +54,37 @@ class Attribute extends TopLevelExprParent, @attribute {
|
||||
/** Gets the element that this attribute is attached to. */
|
||||
Attributable getTarget() { attributes(this, _, result) }
|
||||
|
||||
/** Gets the `i`th argument of this attribute. */
|
||||
/**
|
||||
* Gets the `i`th argument of this attribute. This includes both constructor
|
||||
* arguments and named arguments.
|
||||
*/
|
||||
Expr getArgument(int i) { result = this.getChildExpr(i) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th constructor argument of this attribute. For example, only
|
||||
* `true` is a constructor argument in
|
||||
*
|
||||
* ```
|
||||
* MyAttribute[true, Foo = 0]
|
||||
* ```
|
||||
*/
|
||||
Expr getConstructorArgument(int i) {
|
||||
result = this.getArgument(i) and not exists(result.getExplicitArgumentName())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the named argument `name` of this attribute. For example, only
|
||||
* `0` is a named argument in
|
||||
*
|
||||
* ```
|
||||
* MyAttribute[true, Foo = 0]
|
||||
* ```
|
||||
*/
|
||||
Expr getNamedArgument(string name) {
|
||||
result = this.getArgument(_) and
|
||||
result.getExplicitArgumentName() = name
|
||||
}
|
||||
|
||||
override Location getALocation() { attribute_location(this, result) }
|
||||
|
||||
override string toString() {
|
||||
|
||||
@@ -7,3 +7,5 @@
|
||||
| arguments.cs:39:27:39:27 | 0 | o |
|
||||
| arguments.cs:40:18:40:35 | array creation of type Int32[] | args |
|
||||
| arguments.cs:40:41:40:41 | 0 | o |
|
||||
| arguments.cs:68:28:68:29 | "" | y |
|
||||
| arguments.cs:68:36:68:36 | 0 | x |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
arguments
|
||||
| attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | 0 | attributes.cs:10:26:10:45 | "C# attributes test" |
|
||||
| attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | 0 | attributes.cs:11:32:11:56 | "A test of C# attributes" |
|
||||
| attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | 0 | attributes.cs:12:34:12:35 | "" |
|
||||
@@ -16,3 +17,23 @@
|
||||
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:21 | true |
|
||||
| attributes.cs:54:6:54:16 | [My(...)] | 1 | attributes.cs:54:28:54:29 | "" |
|
||||
| attributes.cs:54:6:54:16 | [My(...)] | 2 | attributes.cs:54:36:54:36 | 0 |
|
||||
constructorArguments
|
||||
| attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | 0 | attributes.cs:10:26:10:45 | "C# attributes test" |
|
||||
| attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | 0 | attributes.cs:11:32:11:56 | "A test of C# attributes" |
|
||||
| attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | 0 | attributes.cs:12:34:12:35 | "" |
|
||||
| attributes.cs:13:12:13:26 | [AssemblyCompany(...)] | 0 | attributes.cs:13:28:13:39 | "Semmle Plc" |
|
||||
| attributes.cs:14:12:14:26 | [AssemblyProduct(...)] | 0 | attributes.cs:14:28:14:34 | "Odasa" |
|
||||
| attributes.cs:15:12:15:28 | [AssemblyCopyright(...)] | 0 | attributes.cs:15:30:15:54 | "Copyright \ufffd Semmle 2018" |
|
||||
| attributes.cs:16:12:16:28 | [AssemblyTrademark(...)] | 0 | attributes.cs:16:30:16:31 | "" |
|
||||
| attributes.cs:17:12:17:26 | [AssemblyCulture(...)] | 0 | attributes.cs:17:28:17:29 | "" |
|
||||
| attributes.cs:22:12:22:21 | [ComVisible(...)] | 0 | attributes.cs:22:23:22:27 | false |
|
||||
| attributes.cs:25:12:25:15 | [Guid(...)] | 0 | attributes.cs:25:17:25:54 | "2f70fdd6-14aa-4850-b053-d547adb1f476" |
|
||||
| attributes.cs:37:12:37:26 | [AssemblyVersion(...)] | 0 | attributes.cs:37:28:37:36 | "1.0.0.0" |
|
||||
| attributes.cs:38:12:38:30 | [AssemblyFileVersion(...)] | 0 | attributes.cs:38:32:38:40 | "1.0.0.0" |
|
||||
| attributes.cs:40:2:40:22 | [AttributeUsage(...)] | 0 | attributes.cs:40:24:40:50 | access to constant All |
|
||||
| attributes.cs:43:6:43:16 | [Conditional(...)] | 0 | attributes.cs:43:18:43:25 | "DEBUG2" |
|
||||
| attributes.cs:51:6:51:16 | [My(...)] | 0 | attributes.cs:51:18:51:22 | false |
|
||||
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:21 | true |
|
||||
namedArguments
|
||||
| attributes.cs:54:6:54:16 | [My(...)] | x | attributes.cs:54:36:54:36 | 0 |
|
||||
| attributes.cs:54:6:54:16 | [My(...)] | y | attributes.cs:54:28:54:29 | "" |
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
import csharp
|
||||
|
||||
from Attribute attribute, int index
|
||||
select attribute, index, attribute.getArgument(index)
|
||||
query predicate arguments(Attribute attribute, int index, Expr e) {
|
||||
e = attribute.getArgument(index)
|
||||
}
|
||||
|
||||
query predicate constructorArguments(Attribute attribute, int index, Expr e) {
|
||||
e = attribute.getConstructorArgument(index)
|
||||
}
|
||||
|
||||
query predicate namedArguments(Attribute attribute, string name, Expr e) {
|
||||
e = attribute.getNamedArgument(name)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user