Skip to content

Commit 81ce29c

Browse files
authored
Merge pull request #4656 from tamasvajk/feature/csharp9-not-pattern
C#: Extract unary patterns
2 parents d7ca065 + 4b32fd0 commit 81ce29c

File tree

15 files changed

+6526
-2563
lines changed

15 files changed

+6526
-2563
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
lgtm,codescanning
2+
* The `UnaryPatternExpr` and `NotPatternExpr` classes have been added to support
3+
C# 9 unary `not` pattern.

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Patterns/Pattern.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ internal static Expression Create(Context cx, PatternSyntax syntax, IExpressionP
2020
case TypePatternSyntax typePattern:
2121
return Expressions.TypeAccess.Create(cx, typePattern.Type, parent, child);
2222

23+
case UnaryPatternSyntax unaryPattern:
24+
return new UnaryPattern(cx, unaryPattern, parent, child);
25+
2326
case DeclarationPatternSyntax declPattern:
2427
// Creates a single local variable declaration.
2528
{
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Microsoft.CodeAnalysis.CSharp.Syntax;
2+
using Semmle.Extraction.Entities;
3+
using Semmle.Extraction.Kinds;
4+
5+
namespace Semmle.Extraction.CSharp.Entities.Expressions
6+
{
7+
internal class UnaryPattern : Expression
8+
{
9+
public UnaryPattern(Context cx, UnaryPatternSyntax syntax, IExpressionParentEntity parent, int child) :
10+
base(new ExpressionInfo(cx, NullType.Create(cx), cx.Create(syntax.GetLocation()), ExprKind.NOT_PATTERN, parent, child, false, null))
11+
{
12+
Pattern.Create(cx, syntax.Pattern, this, 0);
13+
}
14+
}
15+
}

csharp/extractor/Semmle.Extraction.CSharp/Kinds/ExprKind.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ public enum ExprKind
115115
SWITCH_CASE = 118,
116116
ASSIGN_COALESCE = 119,
117117
SUPPRESS_NULLABLE_WARNING = 120,
118-
NAMESPACE_ACCESS = 121
118+
NAMESPACE_ACCESS = 121,
119+
NOT_PATTERN = 126
119120
}
120121
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,12 @@ private predicate hasChildPattern(ControlFlowElement pm, Expr child) {
295295
child = mid.getChild(2).getAChildExpr() or
296296
child = mid.getChild(3).getAChildExpr()
297297
)
298+
or
299+
exists(Expr mid |
300+
hasChildPattern(pm, mid) and
301+
mid instanceof @unary_pattern_expr and
302+
child = mid.getChild(0)
303+
)
298304
}
299305

300306
/**
@@ -444,6 +450,19 @@ class PositionalPatternExpr extends Expr, @positional_pattern_expr {
444450
override string getAPrimaryQlClass() { result = "PositionalPatternExpr" }
445451
}
446452

453+
/** A unary pattern. For example, `not 1`. */
454+
class UnaryPatternExpr extends PatternExpr, @unary_pattern_expr {
455+
/** Gets the underlying pattern. */
456+
PatternExpr getPattern() { result = this.getChild(0) }
457+
}
458+
459+
/** A not pattern. For example, `not 1`. */
460+
class NotPatternExpr extends UnaryPatternExpr, @not_pattern_expr {
461+
override string toString() { result = "not ..." }
462+
463+
override string getAPrimaryQlClass() { result = "NotPatternExpr" }
464+
}
465+
447466
/**
448467
* An expression or statement that matches the value of an expression against
449468
* a pattern. Either an `is` expression or a `case` expression/statement.

csharp/ql/src/semmlecode.csharp.dbscheme

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,11 +1009,14 @@ case @expr.kind of
10091009
| 119 = @assign_coalesce_expr
10101010
| 120 = @suppress_nullable_warning_expr
10111011
| 121 = @namespace_access_expr
1012+
/* C# 9.0 */
1013+
| 126 = @not_pattern_expr
10121014
;
10131015

10141016
@switch = @switch_stmt | @switch_expr;
10151017
@case = @case_stmt | @switch_case_expr;
10161018
@pattern_match = @case | @is_expr;
1019+
@unary_pattern_expr = @not_pattern_expr;
10171020

10181021
@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
10191022
@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;

0 commit comments

Comments
 (0)