Skip to content

Commit 55d47a7

Browse files
committed
C#: Extract modifiers for lambdas (async, static)
1 parent 252692e commit 55d47a7

File tree

12 files changed

+123
-8
lines changed

12 files changed

+123
-8
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* The `AnonymousFunctionExpr` class now extends `Modifiable`. This change allows storing the `async` modifier for lambdas, which was missing before, and the `static` modifier, which was added in C# 9.

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Lambda.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ private void VisitParameter(ParameterSyntax p)
2424
private Lambda(ExpressionNodeInfo info, CSharpSyntaxNode body, IEnumerable<ParameterSyntax> @params)
2525
: base(info)
2626
{
27+
var symbol = cx.GetModel(info.Node).GetSymbolInfo(info.Node).Symbol as IMethodSymbol;
28+
29+
if (symbol is object)
30+
{
31+
Modifier.ExtractStaticModifier(cx, info.Context.TrapWriter.Writer, this, symbol);
32+
Modifier.ExtractAsyncModifier(cx, info.Context.TrapWriter.Writer, this, symbol);
33+
}
34+
else
35+
{
36+
cx.ModelError(info.Node, "Unknown declared symbol");
37+
}
38+
2739
// No need to use `Populate` as the population happens later
2840
cx.PopulateLater(() =>
2941
{

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

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,7 @@ public static void ExtractModifiers(Context cx, TextWriter trapFile, IEntity key
8686
if (symbol.IsSealed)
8787
HasModifier(cx, trapFile, key, "sealed");
8888

89-
var fromSource = symbol.DeclaringSyntaxReferences.Length > 0;
90-
91-
if (symbol.IsStatic && !(symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsConst && !fromSource))
92-
HasModifier(cx, trapFile, key, "static");
89+
ExtractStaticModifier(cx, trapFile, key, symbol);
9390

9491
if (symbol.IsVirtual)
9592
HasModifier(cx, trapFile, key, "virtual");
@@ -104,8 +101,7 @@ public static void ExtractModifiers(Context cx, TextWriter trapFile, IEntity key
104101
if (symbol.IsOverride)
105102
HasModifier(cx, trapFile, key, "override");
106103

107-
if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).IsAsync)
108-
HasModifier(cx, trapFile, key, "async");
104+
ExtractAsyncModifier(cx, trapFile, key, symbol);
109105

110106
if (symbol.IsExtern)
111107
HasModifier(cx, trapFile, key, "extern");
@@ -129,6 +125,20 @@ public static void ExtractModifiers(Context cx, TextWriter trapFile, IEntity key
129125
}
130126
}
131127

128+
public static void ExtractAsyncModifier(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol)
129+
{
130+
if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).IsAsync)
131+
HasModifier(cx, trapFile, key, "async");
132+
}
133+
134+
public static void ExtractStaticModifier(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol)
135+
{
136+
var fromSource = symbol.DeclaringSyntaxReferences.Length > 0;
137+
138+
if (symbol.IsStatic && !(symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsConst && !fromSource))
139+
HasModifier(cx, trapFile, key, "static");
140+
}
141+
132142
public static Modifier Create(Context cx, string modifier)
133143
{
134144
return ModifierFactory.Instance.CreateEntity(cx, (typeof(Modifier), modifier), modifier);

csharp/ql/src/semmle/code/csharp/exprs/Creation.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ class Stackalloc extends ArrayCreation {
407407
* An anonymous function. Either a lambda expression (`LambdaExpr`) or an
408408
* anonymous method expression (`AnonymousMethodExpr`).
409409
*/
410-
class AnonymousFunctionExpr extends Expr, Callable, @anonymous_function_expr {
410+
class AnonymousFunctionExpr extends Expr, Callable, Modifiable, @anonymous_function_expr {
411411
override string getName() { result = "<anonymous>" }
412412

413413
override Type getReturnType() {

csharp/ql/src/semmlecode.csharp.dbscheme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ specific_type_parameter_nullability(
541541

542542
@modifiable = @modifiable_direct | @event_accessor;
543543

544-
@modifiable_direct = @member | @accessor | @local_function;
544+
@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
545545

546546
modifiers(
547547
unique int id: @modifier,

csharp/ql/test/library-tests/csharp9/Discard.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@
66
| Discard.cs:9:13:9:32 | (...) => ... | Discard.cs:9:25:9:25 | _`1 |
77
| Discard.cs:10:13:10:49 | delegate(...) { ... } | Discard.cs:10:27:10:27 | _ |
88
| Discard.cs:10:13:10:49 | delegate(...) { ... } | Discard.cs:10:34:10:34 | _`1 |
9+
| LambdaModifier.cs:11:11:11:27 | (...) => ... | LambdaModifier.cs:11:18:11:18 | x |
10+
| LambdaModifier.cs:12:11:12:20 | (...) => ... | LambdaModifier.cs:12:11:12:11 | x |
11+
| LambdaModifier.cs:13:11:13:51 | delegate(...) { ... } | LambdaModifier.cs:13:32:13:32 | x |
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
4+
public class Class1
5+
{
6+
public async Task M1()
7+
{
8+
void m(Func<int, int> f) { }
9+
10+
const int z = 10;
11+
m(static x => x + z);
12+
m(x => x + z);
13+
m(static delegate (int x) { return x + z; });
14+
15+
await Task.Run(async () => { await Task.CompletedTask; });
16+
}
17+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
| LambdaModifier.cs:11:11:11:27 | (...) => ... | static |
2+
| LambdaModifier.cs:13:11:13:51 | delegate(...) { ... } | static |
3+
| LambdaModifier.cs:15:24:15:64 | (...) => ... | async |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import csharp
2+
3+
from AnonymousFunctionExpr anon, string modifier
4+
where anon.hasModifier(modifier)
5+
select anon, modifier

csharp/ql/test/library-tests/csharp9/LocalFunctions.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
noBody
22
| LocalFunction.cs:16:9:16:41 | localExtern |
33
localFunctionModifier
4+
| LambdaModifier.cs:8:9:8:36 | m | private |
45
| LocalFunction.cs:9:9:12:9 | mul | async |
56
| LocalFunction.cs:9:9:12:9 | mul | private |
67
| LocalFunction.cs:16:9:16:41 | localExtern | extern |

0 commit comments

Comments
 (0)