Skip to content

Commit 65dbb6e

Browse files
authored
Merge pull request github#4612 from tamasvajk/feature/csharp9-local-function-without-body
C#: C#9 Extract local functions without body
2 parents dcc0481 + 1988330 commit 65dbb6e

File tree

8 files changed

+75
-17
lines changed

8 files changed

+75
-17
lines changed

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,7 @@ private class LocalFunctionFactory : ICachedEntityFactory<IMethodSymbol, LocalFu
3434
public override void Populate(TextWriter trapFile)
3535
{
3636
PopulateMethod(trapFile);
37-
38-
// There is a "bug" in Roslyn whereby the IMethodSymbol associated with the local function symbol
39-
// is always static, so we need to go to the syntax reference of the local function to see whether
40-
// the "static" modifier is present.
41-
if (symbol.DeclaringSyntaxReferences.SingleOrDefault().GetSyntax() is LocalFunctionStatementSyntax fn)
42-
{
43-
foreach (var modifier in fn.Modifiers)
44-
{
45-
Modifier.HasModifier(Context, trapFile, this, modifier.Text);
46-
}
47-
}
37+
PopulateModifiers(trapFile);
4838

4939
var originalDefinition = IsSourceDeclaration ? this : Create(Context, symbol.OriginalDefinition);
5040
var returnType = Type.Create(Context, symbol.ReturnType);

csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/LocalFunction.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,8 @@ private IMethodSymbol Symbol
2626
{
2727
get
2828
{
29-
// Ideally model.GetDeclaredSymbol(Stmt) would do
30-
// the right thing but it doesn't exist.
31-
// So instead, we have to do the lookup via GetEnclosingSymbol.
32-
3329
var m = cx.GetModel(Stmt);
34-
var body = Stmt.Body == null ? Stmt.ExpressionBody : (CSharpSyntaxNode)Stmt.Body;
35-
return m.GetEnclosingSymbol(body.GetLocation().SourceSpan.Start) as IMethodSymbol;
30+
return m.GetDeclaredSymbol(Stmt) as IMethodSymbol;
3631
}
3732
}
3833

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
| StaticLocalFunctions.cs:9:9:9:33 | I | private |
12
| StaticLocalFunctions.cs:9:9:9:33 | I | static |
3+
| StaticLocalFunctions.cs:10:9:10:28 | J | private |
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
4+
public class Class1
5+
{
6+
public async Task M1()
7+
{
8+
int? i = 1;
9+
async Task<int?> mul(int mul)
10+
{
11+
return mul * i;
12+
}
13+
14+
await mul(2);
15+
16+
static extern void localExtern();
17+
}
18+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
noBody
2+
| LocalFunction.cs:16:9:16:41 | localExtern |
3+
localFunctionModifier
4+
| LocalFunction.cs:9:9:12:9 | mul | async |
5+
| LocalFunction.cs:9:9:12:9 | mul | private |
6+
| LocalFunction.cs:16:9:16:41 | localExtern | extern |
7+
| LocalFunction.cs:16:9:16:41 | localExtern | private |
8+
| LocalFunction.cs:16:9:16:41 | localExtern | static |
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
noBody
2+
| LocalFunction.cs:16:9:16:41 | localExtern |
3+
localFunctionModifier
4+
| LocalFunction.cs:9:9:12:9 | mul | async |
5+
| LocalFunction.cs:9:9:12:9 | mul | private |
6+
| LocalFunction.cs:16:9:16:41 | localExtern | extern |
7+
| LocalFunction.cs:16:9:16:41 | localExtern | private |
8+
| LocalFunction.cs:16:9:16:41 | localExtern | static |
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import csharp
2+
3+
query predicate noBody(LocalFunction lf) { not lf.hasBody() }
4+
5+
query predicate localFunctionModifier(LocalFunction lf, string modifier) {
6+
lf.hasModifier(modifier)
7+
}

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,36 @@ Discard.cs:
4747
# 10| 4: [BlockStmt] {...}
4848
# 10| 0: [ReturnStmt] return ...;
4949
# 10| 0: [IntLiteral] 0
50+
LocalFunction.cs:
51+
# 4| [Class] Class1
52+
# 6| 5: [Method] M1
53+
# 6| -1: [TypeMention] Task
54+
# 7| 4: [BlockStmt] {...}
55+
# 8| 0: [LocalVariableDeclStmt] ... ...;
56+
# 8| 0: [LocalVariableDeclAndInitExpr] Nullable<Int32> i = ...
57+
# 8| -1: [TypeMention] int?
58+
# 8| 1: [TypeMention] int
59+
# 8| 0: [LocalVariableAccess] access to local variable i
60+
# 8| 1: [CastExpr] (...) ...
61+
# 8| 1: [IntLiteral] 1
62+
# 9| 1: [LocalFunctionStmt] mul(...)
63+
# 9| 0: [LocalFunction] mul
64+
#-----| 2: (Parameters)
65+
# 9| 0: [Parameter] mul
66+
# 9| -1: [TypeMention] int
67+
# 10| 4: [BlockStmt] {...}
68+
# 11| 0: [ReturnStmt] return ...;
69+
# 11| 0: [MulExpr] ... * ...
70+
# 11| 0: [CastExpr] (...) ...
71+
# 11| 1: [ParameterAccess] access to parameter mul
72+
# 11| 1: [LocalVariableAccess] access to local variable i
73+
# 14| 2: [ExprStmt] ...;
74+
# 14| 0: [AwaitExpr] await ...
75+
# 14| 0: [LocalFunctionCall] call to local function mul
76+
# 14| -1: [LocalFunctionAccess] access to local function mul
77+
# 14| 0: [IntLiteral] 2
78+
# 16| 3: [LocalFunctionStmt] localExtern(...)
79+
# 16| 0: [LocalFunction] localExtern
5080
NativeInt.cs:
5181
# 3| [Class] NativeInt
5282
# 5| 5: [Method] M1

0 commit comments

Comments
 (0)