mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
Merge pull request #11594 from michaelnebel/csharp/listpattern
C#: Support List and Slice patterns.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
class Expression extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class TypeOrRef extends @type_or_ref {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Expression e, int k, int kind, TypeOrRef t
|
||||
where
|
||||
expressions(e, k, t) and
|
||||
if k = [131, 132] then kind = 106 else kind = k
|
||||
select e, kind, t
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Remove list- and slice pattern expression kinds.
|
||||
compatibility: backwards
|
||||
expressions.rel: run expressions.qlo
|
||||
@@ -0,0 +1,15 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Kinds;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
{
|
||||
internal class ListPattern : Expression
|
||||
{
|
||||
internal ListPattern(Context cx, ListPatternSyntax syntax, IExpressionParentEntity parent, int child) :
|
||||
base(new ExpressionInfo(cx, null, cx.CreateLocation(syntax.GetLocation()), ExprKind.LIST_PATTERN, parent, child, false, null))
|
||||
{
|
||||
syntax.Patterns.ForEach((p, i) => Pattern.Create(cx, p, this, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,12 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
case DiscardPatternSyntax dp:
|
||||
return new Discard(cx, dp, parent, child);
|
||||
|
||||
case ListPatternSyntax listPattern:
|
||||
return new ListPattern(cx, listPattern, parent, child);
|
||||
|
||||
case SlicePatternSyntax slicePattern:
|
||||
return new SlicePattern(cx, slicePattern, parent, child);
|
||||
|
||||
default:
|
||||
throw new InternalError(syntax, "Pattern not handled");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Kinds;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
{
|
||||
internal class SlicePattern : Expression
|
||||
{
|
||||
public SlicePattern(Context cx, SlicePatternSyntax syntax, IExpressionParentEntity parent, int child) :
|
||||
base(new ExpressionInfo(cx, null, cx.CreateLocation(syntax.GetLocation()), ExprKind.SLICE_PATTERN, parent, child, false, null))
|
||||
{
|
||||
if (syntax.Pattern is not null)
|
||||
{
|
||||
Pattern.Create(cx, syntax.Pattern, this, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,6 +125,8 @@ namespace Semmle.Extraction.Kinds
|
||||
OR_PATTERN = 128,
|
||||
FUNCTION_POINTER_INVOCATION = 129,
|
||||
WITH = 130,
|
||||
DEFINE_SYMBOL = 999
|
||||
LIST_PATTERN = 131,
|
||||
SLICE_PATTERN = 132,
|
||||
DEFINE_SYMBOL = 999,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,19 @@ namespace Semmle.Util
|
||||
a(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the action <paramref name="a"/> to each item and its index in this collection.
|
||||
/// </summary>
|
||||
public static void ForEach<T>(this IEnumerable<T> items, Action<T, int> a)
|
||||
{
|
||||
var i = 0;
|
||||
foreach (var item in items)
|
||||
{
|
||||
a(item, i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces enumeration of this collection and discards the result.
|
||||
/// </summary>
|
||||
|
||||
4
csharp/ql/lib/change-notes/2022-12-08-listpatterns.md
Normal file
4
csharp/ql/lib/change-notes/2022-12-08-listpatterns.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* C# 11: Added support for list- and slice patterns in the extractor.
|
||||
@@ -321,6 +321,18 @@ private predicate hasChildPattern(ControlFlowElement pm, Expr child) {
|
||||
mid instanceof @tuple_expr and
|
||||
child = mid.getAChildExpr()
|
||||
)
|
||||
or
|
||||
exists(Expr mid |
|
||||
hasChildPattern(pm, mid) and
|
||||
mid instanceof @list_pattern_expr and
|
||||
child = mid.getAChildExpr()
|
||||
)
|
||||
or
|
||||
exists(Expr mid |
|
||||
hasChildPattern(pm, mid) and
|
||||
mid instanceof @slice_pattern_expr and
|
||||
child = mid.getAChildExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -506,6 +518,26 @@ class PositionalPatternExpr extends PatternExpr, @positional_pattern_expr {
|
||||
override string getAPrimaryQlClass() { result = "PositionalPatternExpr" }
|
||||
}
|
||||
|
||||
/** A list pattern. For example `[1, 2, int y]` in `x is [1, 2, int y]`. */
|
||||
class ListPatternExpr extends PatternExpr, @list_pattern_expr {
|
||||
override string toString() { result = "[ ... ]" }
|
||||
|
||||
/** Gets the `n`th pattern. */
|
||||
PatternExpr getPattern(int n) { result = this.getChild(n) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ListPatternExpr" }
|
||||
}
|
||||
|
||||
/** A slice pattern. For example `..` in `x is [1, .., 2]. */
|
||||
class SlicePatternExpr extends PatternExpr, @slice_pattern_expr {
|
||||
override string toString() { result = ".." }
|
||||
|
||||
/** Gets the subpattern, if any. */
|
||||
PatternExpr getPattern() { result = this.getChild(0) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SlicePatternExpr" }
|
||||
}
|
||||
|
||||
/** A unary pattern. For example, `not 1`. */
|
||||
class UnaryPatternExpr extends PatternExpr, @unary_pattern_expr {
|
||||
/** Gets the underlying pattern. */
|
||||
|
||||
@@ -1134,6 +1134,9 @@ case @expr.kind of
|
||||
| 128 = @or_pattern_expr
|
||||
| 129 = @function_pointer_invocation_expr
|
||||
| 130 = @with_expr
|
||||
/* C# 11.0 */
|
||||
| 131 = @list_pattern_expr
|
||||
| 132 = @slice_pattern_expr
|
||||
/* Preprocessor */
|
||||
| 999 = @define_symbol_expr
|
||||
;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Add list- and slice pattern expressions kinds.
|
||||
compatibility: backwards
|
||||
38
csharp/ql/test/library-tests/csharp11/ListPattern.cs
Normal file
38
csharp/ql/test/library-tests/csharp11/ListPattern.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
class ListPattern
|
||||
{
|
||||
public void M1(int[] x)
|
||||
{
|
||||
if (x is []) { }
|
||||
if (x is [1]) { }
|
||||
if (x is [_, 2]) { }
|
||||
if (x is [var y, 3, 4]) { }
|
||||
if (x is [5 or 6, _, 7]) { }
|
||||
if (x is [var a, .., 2]) { }
|
||||
if (x is [var b, .. { Length: 2 or 5 }, 2]) { }
|
||||
}
|
||||
|
||||
public void M2(string[] x)
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case []:
|
||||
break;
|
||||
case ["A"]:
|
||||
break;
|
||||
case [_, "B"]:
|
||||
break;
|
||||
case [var y, "C", "D"]:
|
||||
break;
|
||||
case ["E" or "F", _, "G"]:
|
||||
break;
|
||||
case [var a, .., "H"]:
|
||||
break;
|
||||
case [var b, .. var c, "I"]:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
csharp/ql/test/library-tests/csharp11/listPattern.expected
Normal file
20
csharp/ql/test/library-tests/csharp11/listPattern.expected
Normal file
@@ -0,0 +1,20 @@
|
||||
listPattern
|
||||
| ListPattern.cs:7:18:7:19 | [ ... ] | |
|
||||
| ListPattern.cs:8:18:8:20 | [ ... ] | 1 |
|
||||
| ListPattern.cs:9:18:9:23 | [ ... ] | _, 2 |
|
||||
| ListPattern.cs:10:18:10:30 | [ ... ] | Int32 y, 3, 4 |
|
||||
| ListPattern.cs:11:18:11:31 | [ ... ] | ... or ..., _, 7 |
|
||||
| ListPattern.cs:12:18:12:31 | [ ... ] | Int32 a, .., 2 |
|
||||
| ListPattern.cs:13:18:13:50 | [ ... ] | Int32 b, .., 2 |
|
||||
| ListPattern.cs:20:18:20:19 | [ ... ] | |
|
||||
| ListPattern.cs:22:18:22:22 | [ ... ] | "A" |
|
||||
| ListPattern.cs:24:18:24:25 | [ ... ] | _, "B" |
|
||||
| ListPattern.cs:26:18:26:34 | [ ... ] | String y, "C", "D" |
|
||||
| ListPattern.cs:28:18:28:37 | [ ... ] | ... or ..., _, "G" |
|
||||
| ListPattern.cs:30:18:30:33 | [ ... ] | String a, .., "H" |
|
||||
| ListPattern.cs:32:18:32:39 | [ ... ] | String b, .., "I" |
|
||||
slicePattern
|
||||
| ListPattern.cs:12:26:12:27 | .. | ..: |
|
||||
| ListPattern.cs:13:26:13:46 | .. | ..:{ ... } |
|
||||
| ListPattern.cs:30:26:30:27 | .. | ..: |
|
||||
| ListPattern.cs:32:26:32:33 | .. | ..:String[] c |
|
||||
19
csharp/ql/test/library-tests/csharp11/listPattern.ql
Normal file
19
csharp/ql/test/library-tests/csharp11/listPattern.ql
Normal file
@@ -0,0 +1,19 @@
|
||||
import csharp
|
||||
|
||||
private string childPatterns(ListPatternExpr e) {
|
||||
result = concat(string child, int n | child = e.getPattern(n).toString() | child, ", " order by n)
|
||||
}
|
||||
|
||||
query predicate listPattern(ListPatternExpr pattern, string children) {
|
||||
pattern.getFile().getStem() = "ListPattern" and
|
||||
children = childPatterns(pattern)
|
||||
}
|
||||
|
||||
query predicate slicePattern(SlicePatternExpr pattern, string s) {
|
||||
pattern.getFile().getStem() = "ListPattern" and
|
||||
exists(string child |
|
||||
if exists(pattern.getPattern()) then child = pattern.getPattern().toString() else child = ""
|
||||
|
|
||||
s = pattern.toString() + ":" + child
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user