Skip to content

Commit c04e344

Browse files
authored
Merge pull request github#7749 from michaelnebel/csharp/lambda-improvements
C# 10 - Lambda improvements.
2 parents b62df5a + 99f89f1 commit c04e344

File tree

19 files changed

+10326
-1907
lines changed

19 files changed

+10326
-1907
lines changed

csharp/downgrades/4b9c288ece4218779b6113b17af42795f4bbbee1/old.dbscheme

Lines changed: 2058 additions & 0 deletions
Large diffs are not rendered by default.

csharp/downgrades/4b9c288ece4218779b6113b17af42795f4bbbee1/semmlecode.csharp.dbscheme

Lines changed: 2054 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
description: Remove 'lambda_expr_return_type' relation.
2+
compatibility: backwards
3+
lambda_expr_return_type.rel: delete

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ private void VisitParameter(ParameterSyntax p)
2222
Parameter.Create(Context, symbol, this);
2323
}
2424

25-
private Lambda(ExpressionNodeInfo info, CSharpSyntaxNode body, IEnumerable<ParameterSyntax> @params)
25+
private Lambda(ExpressionNodeInfo info, CSharpSyntaxNode body, IEnumerable<ParameterSyntax> @params, TypeSyntax? @return)
2626
: base(info)
2727
{
2828
if (Context.GetModel(info.Node).GetSymbolInfo(info.Node).Symbol is IMethodSymbol symbol)
2929
{
3030
Modifier.ExtractModifiers(Context, info.Context.TrapWriter.Writer, this, symbol);
31+
Attribute.ExtractAttributes(Context, symbol, this);
3132
}
3233
else
3334
{
@@ -40,6 +41,13 @@ private Lambda(ExpressionNodeInfo info, CSharpSyntaxNode body, IEnumerable<Param
4041
foreach (var param in @params)
4142
VisitParameter(param);
4243

44+
if (@return is not null)
45+
{
46+
var symbol = Context.GetType(@return);
47+
var type = Entities.Type.Create(Context, symbol);
48+
var trapFile = Context.TrapWriter.Writer;
49+
trapFile.lambda_expr_return_type(this, type.TypeRef);
50+
}
4351
if (body is ExpressionSyntax exprBody)
4452
Create(Context, exprBody, this, 0);
4553
else if (body is BlockSyntax blockBody)
@@ -50,17 +58,17 @@ private Lambda(ExpressionNodeInfo info, CSharpSyntaxNode body, IEnumerable<Param
5058
}
5159

5260
private Lambda(ExpressionNodeInfo info, ParenthesizedLambdaExpressionSyntax node)
53-
: this(info.SetKind(ExprKind.LAMBDA), node.Body, node.ParameterList.Parameters) { }
61+
: this(info.SetKind(ExprKind.LAMBDA), node.Body, node.ParameterList.Parameters, node.ReturnType) { }
5462

5563
public static Lambda Create(ExpressionNodeInfo info, ParenthesizedLambdaExpressionSyntax node) => new Lambda(info, node);
5664

5765
private Lambda(ExpressionNodeInfo info, SimpleLambdaExpressionSyntax node)
58-
: this(info.SetKind(ExprKind.LAMBDA), node.Body, Enumerators.Singleton(node.Parameter)) { }
66+
: this(info.SetKind(ExprKind.LAMBDA), node.Body, Enumerators.Singleton(node.Parameter), null) { }
5967

6068
public static Lambda Create(ExpressionNodeInfo info, SimpleLambdaExpressionSyntax node) => new Lambda(info, node);
6169

6270
private Lambda(ExpressionNodeInfo info, AnonymousMethodExpressionSyntax node) :
63-
this(info.SetKind(ExprKind.ANONYMOUS_METHOD), node.Body, node.ParameterList is null ? Enumerable.Empty<ParameterSyntax>() : node.ParameterList.Parameters)
71+
this(info.SetKind(ExprKind.ANONYMOUS_METHOD), node.Body, node.ParameterList is null ? Enumerable.Empty<ParameterSyntax>() : node.ParameterList.Parameters, null)
6472
{ }
6573

6674
public static Lambda Create(ExpressionNodeInfo info, AnonymousMethodExpressionSyntax node) => new Lambda(info, node);

csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,9 @@ internal static void indexer_location(this TextWriter trapFile, Indexer indexer,
215215
internal static void indexers(this TextWriter trapFile, Indexer propKey, string name, Type declaringType, Type memberType, Indexer unboundProperty) =>
216216
trapFile.WriteTuple("indexers", propKey, name, declaringType, memberType, unboundProperty);
217217

218+
internal static void lambda_expr_return_type(this TextWriter trapFile, Lambda expr, Type returnType) =>
219+
trapFile.WriteTuple("lambda_expr_return_type", expr, returnType);
220+
218221
internal static void local_function_stmts(this TextWriter trapFile, Entities.Statements.LocalFunction fnStmt, LocalFunction fn) =>
219222
trapFile.WriteTuple("local_function_stmts", fnStmt, fn);
220223

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
category: majorAnalysis
3+
---
4+
Added support for C# 10 lambda improvements
5+
* Explicit return types on lambda expressions.
6+
* Lambda expression can be tagged with method and return value attributes.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ private import TypeRef
1010
* An element that can have attributes. Either an assembly (`Assembly`), a field (`Field`),
1111
* a parameter (`Parameter`), an operator (`Operator`), a method (`Method`), a constructor (`Constructor`),
1212
* a destructor (`Destructor`), a callable accessor (`CallableAccessor`), a value or reference type
13-
* (`ValueOrRefType`), a declaration with accessors (`DeclarationWithAccessors`), or a local function
14-
* (`LocalFunction`).
13+
* (`ValueOrRefType`), a declaration with accessors (`DeclarationWithAccessors`), a local function
14+
* (`LocalFunction`) or a lambda expression (`LambdaExp`).
1515
*/
1616
class Attributable extends @attributable {
1717
/** Gets an attribute attached to this element, if any. */

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import Expr
66
import semmle.code.csharp.Callable
77
private import semmle.code.csharp.frameworks.system.linq.Expressions
8+
private import semmle.code.csharp.TypeRef
89

910
/**
1011
* Either an object initializer (`ObjectInitializer`) or a collection
@@ -434,6 +435,12 @@ class AnonymousFunctionExpr extends Expr, Callable, Modifiable, @anonymous_funct
434435
* A lambda expression, for example `(int x) => x + 1`.
435436
*/
436437
class LambdaExpr extends AnonymousFunctionExpr, @lambda_expr {
438+
/* Holds if this lambda expression has explicit return type. */
439+
predicate hasExplicitReturnType() { lambda_expr_return_type(this, _) }
440+
441+
/* Gets the explicit return type of this lambda expression, if any. */
442+
Type getExplicitReturnType() { lambda_expr_return_type(this, getTypeRef(result)) }
443+
437444
override string toString() { result = "(...) => ..." }
438445

439446
override string getAPrimaryQlClass() { result = "LambdaExpr" }

csharp/ql/lib/semmlecode.csharp.dbscheme

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ sourceLocationPrefix(
191191

192192
@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
193193
| @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
194-
| @local_function;
194+
| @local_function | @lambda_expr;
195195

196196
/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
197197

@@ -1269,6 +1269,10 @@ expr_argument_name(
12691269
unique int id: @expr ref,
12701270
string name: string ref);
12711271

1272+
lambda_expr_return_type(
1273+
unique int id: @lambda_expr ref,
1274+
int type_id: @type_or_ref ref);
1275+
12721276
/** CONTROL/DATA FLOW **/
12731277

12741278
@control_flow_element = @stmt | @expr;

0 commit comments

Comments
 (0)