mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Revert "C#: Revert "Merge pull request #4653 from tamasvajk/feature/csharp9-relational-pattern""
This commit is contained in:
3
csharp/change-notes/2020-11-19-Relational-pattern.md
Normal file
3
csharp/change-notes/2020-11-19-Relational-pattern.md
Normal file
@@ -0,0 +1,3 @@
|
||||
lgtm,codescanning
|
||||
* The `RelationalPatternExpr` and its 4 sub class have been added to support C# 9
|
||||
relational `<`, `>`, `<=`, and `>=` patterns.
|
||||
@@ -42,6 +42,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
case RecursivePatternSyntax recPattern:
|
||||
return new RecursivePattern(cx, recPattern, parent, child);
|
||||
|
||||
case RelationalPatternSyntax relPattern:
|
||||
return new RelationalPattern(cx, relPattern, parent, child);
|
||||
|
||||
case VarPatternSyntax varPattern:
|
||||
switch (varPattern.Designation)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,6 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
/// <param name="syntax">The syntax node of the recursive pattern.</param>
|
||||
/// <param name="parent">The parent pattern/expression.</param>
|
||||
/// <param name="child">The child index of this pattern.</param>
|
||||
/// <param name="isTopLevel">If this pattern is in the top level of a case/is. In that case, the variable and type access are populated elsewhere.</param>
|
||||
public RecursivePattern(Context cx, RecursivePatternSyntax syntax, IExpressionParentEntity parent, int child) :
|
||||
base(new ExpressionInfo(cx, Entities.NullType.Create(cx), cx.Create(syntax.GetLocation()), ExprKind.RECURSIVE_PATTERN, parent, child, false, null))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Semmle.Extraction.Kinds;
|
||||
using Semmle.Extraction.Entities;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
{
|
||||
internal class RelationalPattern : Expression
|
||||
{
|
||||
public RelationalPattern(Context cx, RelationalPatternSyntax syntax, IExpressionParentEntity parent, int child) :
|
||||
base(new ExpressionInfo(cx, NullType.Create(cx), cx.Create(syntax.GetLocation()), GetKind(syntax.OperatorToken), parent, child, false, null))
|
||||
{
|
||||
Expression.Create(cx, syntax.Expression, this, 0);
|
||||
}
|
||||
|
||||
private static ExprKind GetKind(SyntaxToken operatorToken)
|
||||
{
|
||||
return operatorToken.Kind() switch
|
||||
{
|
||||
SyntaxKind.LessThanEqualsToken => ExprKind.LE_PATTERN,
|
||||
SyntaxKind.GreaterThanEqualsToken => ExprKind.GE_PATTERN,
|
||||
SyntaxKind.LessThanToken => ExprKind.LT_PATTERN,
|
||||
SyntaxKind.GreaterThanToken => ExprKind.GT_PATTERN,
|
||||
_ => throw new InternalError(operatorToken.Parent, $"Relation pattern with operator token '{operatorToken.Kind()}' is not supported."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,6 +115,10 @@ namespace Semmle.Extraction.Kinds
|
||||
SWITCH_CASE = 118,
|
||||
ASSIGN_COALESCE = 119,
|
||||
SUPPRESS_NULLABLE_WARNING = 120,
|
||||
NAMESPACE_ACCESS = 121
|
||||
NAMESPACE_ACCESS = 121,
|
||||
LT_PATTERN = 122,
|
||||
GT_PATTERN = 123,
|
||||
LE_PATTERN = 124,
|
||||
GE_PATTERN = 125,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +342,45 @@ class ConstantPatternExpr extends PatternExpr {
|
||||
override string getAPrimaryQlClass() { result = "ConstantPatternExpr" }
|
||||
}
|
||||
|
||||
/** A relational pattern, for example `>1` in `x is >1`. */
|
||||
class RelationalPatternExpr extends PatternExpr, @relational_pattern_expr {
|
||||
/** Gets the name of the operator in this pattern. */
|
||||
string getOperator() { none() }
|
||||
|
||||
/** Gets the expression of this relational pattern. */
|
||||
Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
override string toString() { result = getOperator() + " ..." }
|
||||
}
|
||||
|
||||
/** A less-than pattern, for example `< 10` in `x is < 10`. */
|
||||
class LTPattern extends RelationalPatternExpr, @lt_pattern_expr {
|
||||
override string getOperator() { result = "<" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LTPattern" }
|
||||
}
|
||||
|
||||
/** A greater-than pattern, for example `> 10` in `x is > 10`. */
|
||||
class GTPattern extends RelationalPatternExpr, @gt_pattern_expr {
|
||||
override string getOperator() { result = ">" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GTPattern" }
|
||||
}
|
||||
|
||||
/** A less-than or equals pattern, for example `<= 10` in `x is <= 10`. */
|
||||
class LEPattern extends RelationalPatternExpr, @le_pattern_expr {
|
||||
override string getOperator() { result = "<=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LEPattern" }
|
||||
}
|
||||
|
||||
/** A greater-than or equals pattern, for example `>= 10` in `x is >= 10` */
|
||||
class GEPattern extends RelationalPatternExpr, @ge_pattern_expr {
|
||||
override string getOperator() { result = ">=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GEPattern" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type pattern, for example `string` in `x is string`, `string s` in
|
||||
* `x is string s`, or `string _` in `x is string _`.
|
||||
|
||||
@@ -998,11 +998,17 @@ case @expr.kind of
|
||||
| 119 = @assign_coalesce_expr
|
||||
| 120 = @suppress_nullable_warning_expr
|
||||
| 121 = @namespace_access_expr
|
||||
/* C# 9.0 */
|
||||
| 122 = @lt_pattern_expr
|
||||
| 123 = @gt_pattern_expr
|
||||
| 124 = @le_pattern_expr
|
||||
| 125 = @ge_pattern_expr
|
||||
;
|
||||
|
||||
@switch = @switch_stmt | @switch_expr;
|
||||
@case = @case_stmt | @switch_case_expr;
|
||||
@pattern_match = @case | @is_expr;
|
||||
@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
|
||||
|
||||
@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
|
||||
@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
|
||||
|
||||
@@ -335,6 +335,63 @@ ParenthesizedPattern.cs:
|
||||
# 27| 0: [TypeAccessPatternExpr] access to type String
|
||||
# 27| 0: [TypeMention] string
|
||||
# 27| 2: [IntLiteral] 5
|
||||
RelationalPattern.cs:
|
||||
# 3| [Class] RelationalPattern
|
||||
# 5| 5: [Method] M1
|
||||
# 5| -1: [TypeMention] bool
|
||||
#-----| 2: (Parameters)
|
||||
# 5| 0: [Parameter] c
|
||||
# 5| -1: [TypeMention] char
|
||||
# 6| 4: [IsExpr] ... is ...
|
||||
# 6| 0: [ParameterAccess] access to parameter c
|
||||
# 6| 1: [GEPattern] >= ...
|
||||
# 6| 0: [CharLiteral] a
|
||||
# 7| 6: [Method] M2
|
||||
# 7| -1: [TypeMention] bool
|
||||
#-----| 2: (Parameters)
|
||||
# 7| 0: [Parameter] c
|
||||
# 7| -1: [TypeMention] char
|
||||
# 8| 4: [IsExpr] ... is ...
|
||||
# 8| 0: [ParameterAccess] access to parameter c
|
||||
# 8| 1: [GTPattern] > ...
|
||||
# 8| 0: [CharLiteral] a
|
||||
# 9| 7: [Method] M3
|
||||
# 9| -1: [TypeMention] bool
|
||||
#-----| 2: (Parameters)
|
||||
# 9| 0: [Parameter] c
|
||||
# 9| -1: [TypeMention] char
|
||||
# 10| 4: [IsExpr] ... is ...
|
||||
# 10| 0: [ParameterAccess] access to parameter c
|
||||
# 10| 1: [LEPattern] <= ...
|
||||
# 10| 0: [CharLiteral] a
|
||||
# 11| 8: [Method] M4
|
||||
# 11| -1: [TypeMention] bool
|
||||
#-----| 2: (Parameters)
|
||||
# 11| 0: [Parameter] c
|
||||
# 11| -1: [TypeMention] char
|
||||
# 12| 4: [IsExpr] ... is ...
|
||||
# 12| 0: [ParameterAccess] access to parameter c
|
||||
# 12| 1: [LTPattern] < ...
|
||||
# 12| 0: [CharLiteral] a
|
||||
# 14| 9: [Method] M5
|
||||
# 14| -1: [TypeMention] string
|
||||
#-----| 2: (Parameters)
|
||||
# 14| 0: [Parameter] i
|
||||
# 14| -1: [TypeMention] int
|
||||
# 15| 4: [BlockStmt] {...}
|
||||
# 16| 0: [ReturnStmt] return ...;
|
||||
# 16| 0: [SwitchExpr] ... switch { ... }
|
||||
# 16| -1: [ParameterAccess] access to parameter i
|
||||
# 18| 0: [SwitchCaseExpr] ... => ...
|
||||
# 18| 0: [ConstantPatternExpr,IntLiteral] 1
|
||||
# 18| 2: [StringLiteral] "1"
|
||||
# 19| 1: [SwitchCaseExpr] ... => ...
|
||||
# 19| 0: [GTPattern] > ...
|
||||
# 19| 0: [IntLiteral] 1
|
||||
# 19| 2: [StringLiteral] ">1"
|
||||
# 20| 2: [SwitchCaseExpr] ... => ...
|
||||
# 20| 0: [DiscardPatternExpr] _
|
||||
# 20| 2: [StringLiteral] "other"
|
||||
TargetType.cs:
|
||||
# 5| [Class] TargetType
|
||||
# 7| 5: [Method] M2
|
||||
|
||||
23
csharp/ql/test/library-tests/csharp9/RelationalPattern.cs
Normal file
23
csharp/ql/test/library-tests/csharp9/RelationalPattern.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
|
||||
public class RelationalPattern
|
||||
{
|
||||
public static bool M1(char c) =>
|
||||
c is >= 'a';
|
||||
public static bool M2(char c) =>
|
||||
c is > 'a';
|
||||
public static bool M3(char c) =>
|
||||
c is <= 'a';
|
||||
public static bool M4(char c) =>
|
||||
c is < 'a';
|
||||
|
||||
public static string M5(int i)
|
||||
{
|
||||
return i switch
|
||||
{
|
||||
1 => "1",
|
||||
>1 => ">1",
|
||||
_ => "other"
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
| RelationalPattern.cs:6:14:6:19 | >= ... | >= |
|
||||
| RelationalPattern.cs:8:14:8:18 | > ... | > |
|
||||
| RelationalPattern.cs:10:14:10:19 | <= ... | <= |
|
||||
| RelationalPattern.cs:12:14:12:18 | < ... | < |
|
||||
| RelationalPattern.cs:19:13:19:14 | > ... | > |
|
||||
@@ -0,0 +1,4 @@
|
||||
import csharp
|
||||
|
||||
from RelationalPatternExpr p
|
||||
select p, p.getOperator()
|
||||
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 'relational_pattern_expr' and its four subtypes ('<', '>', '<=', '>=')
|
||||
compatibility: backwards
|
||||
Reference in New Issue
Block a user