зеркало из https://github.com/github/codeql.git
Merge pull request #1392 from calumgrant/cs/cs8/static-using-null
C#: More C# 8 features
This commit is contained in:
Коммит
51d6858cd0
|
@ -13,6 +13,10 @@
|
|||
* The following C# 8 features are now extracted:
|
||||
- Range expressions
|
||||
- Recursive patterns
|
||||
- Using declaration statements
|
||||
- `static` modifiers on local functions
|
||||
- Null-coalescing assignment expressions
|
||||
|
||||
* The `unmanaged` type parameter constraint is now extracted.
|
||||
|
||||
## Changes to QL libraries
|
||||
|
@ -20,6 +24,7 @@
|
|||
* The class `Attribute` has two new predicates: `getConstructorArgument()` and `getNamedArgument()`. The first predicate returns arguments to the underlying constructor call and the latter returns named arguments for initializing fields and properties.
|
||||
* The class `TypeParameterConstraints` has a new predicate `hasUnmanagedTypeConstraint()`, indicating that the type parameter has the `unmanaged` constraint.
|
||||
* The following QL classes have been added to model C# 8 features:
|
||||
- Class `AssignCoalesceExpr` models null-coalescing assignment, for example `x ??= y`
|
||||
- Class `IndexExpr` models from-end index expressions, for example `^1`
|
||||
- Class `PatternExpr` is an `Expr` that appears in a pattern. It has the new subclasses `DiscardPatternExpr`, `LabeledPatternExpr`, `RecursivePatternExpr`, `TypeAccessPatternExpr`, `TypePatternExpr`, and `VariablePatternExpr`.
|
||||
- Class `PatternMatch` models a pattern being matched. It has the subclasses `Case` and `IsExpr`.
|
||||
|
@ -31,5 +36,6 @@
|
|||
- Classes `IsConstantExpr`, `IsTypeExpr` and `IsPatternExpr` are deprecated in favour of `IsExpr`
|
||||
- Class `Switch` models both `SwitchExpr` and `SwitchStmt`
|
||||
- Class `Case` models both `CaseStmt` and `SwitchCaseExpr`
|
||||
- Class `UsingStmt` models both `UsingBlockStmt` and `UsingDeclStmt`
|
||||
|
||||
## Changes to autobuilder
|
||||
|
|
|
@ -71,6 +71,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||
return ExprKind.ASSIGN_LSHIFT;
|
||||
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
|
||||
return ExprKind.ASSIGN_RSHIFT;
|
||||
case SyntaxKind.QuestionQuestionEqualsToken:
|
||||
return ExprKind.ASSIGN_COALESCE;
|
||||
default:
|
||||
cx.ModelError(syntax, "Unrecognised assignment type " + GetKind(cx, syntax));
|
||||
return ExprKind.UNKNOWN;
|
||||
|
@ -142,6 +144,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||
return ExprKind.SUB;
|
||||
case ExprKind.ASSIGN_XOR:
|
||||
return ExprKind.BIT_XOR;
|
||||
case ExprKind.ASSIGN_COALESCE:
|
||||
return ExprKind.NULL_COALESCING;
|
||||
default:
|
||||
cx.ModelError(Syntax, "Couldn't unfold assignment of type " + kind);
|
||||
return ExprKind.UNKNOWN;
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|||
case SyntaxKind.RightShiftAssignmentExpression:
|
||||
case SyntaxKind.DivideAssignmentExpression:
|
||||
case SyntaxKind.ModuloAssignmentExpression:
|
||||
case SyntaxKind.CoalesceAssignmentExpression:
|
||||
return Assignment.Create(info);
|
||||
|
||||
case SyntaxKind.ObjectCreationExpression:
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using System.Linq;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
|
@ -39,6 +41,18 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||
public override void Populate()
|
||||
{
|
||||
PopulateMethod();
|
||||
|
||||
// There is a "bug" in Roslyn whereby the IMethodSymbol associated with the local function symbol
|
||||
// is always static, so we need to go to the syntax reference of the local function to see whether
|
||||
// the "static" modifier is present.
|
||||
if (symbol.DeclaringSyntaxReferences.SingleOrDefault().GetSyntax() is LocalFunctionStatementSyntax fn)
|
||||
{
|
||||
foreach(var modifier in fn.Modifiers)
|
||||
{
|
||||
Modifier.HasModifier(Context, this, modifier.Text);
|
||||
}
|
||||
}
|
||||
|
||||
var originalDefinition = IsSourceDeclaration ? this : Create(Context, symbol.OriginalDefinition);
|
||||
var returnType = Type.Create(Context, symbol.ReturnType);
|
||||
Context.Emit(Tuples.local_functions(this, symbol.Name, returnType, originalDefinition));
|
||||
|
|
|
@ -6,8 +6,19 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
|
|||
{
|
||||
class LocalDeclaration : Statement<LocalDeclarationStatementSyntax>
|
||||
{
|
||||
static StmtKind GetKind(LocalDeclarationStatementSyntax declStmt)
|
||||
{
|
||||
if (declStmt.UsingKeyword.RawKind != 0)
|
||||
return StmtKind.USING_DECL;
|
||||
|
||||
if (declStmt.IsConst)
|
||||
return StmtKind.CONST_DECL;
|
||||
|
||||
return StmtKind.VAR_DECL;
|
||||
}
|
||||
|
||||
LocalDeclaration(Context cx, LocalDeclarationStatementSyntax declStmt, IStatementParentEntity parent, int child)
|
||||
: base(cx, declStmt, declStmt.IsConst ? StmtKind.CONST_DECL : StmtKind.VAR_DECL, parent, child) { }
|
||||
: base(cx, declStmt, GetKind(declStmt), parent, child) { }
|
||||
|
||||
public static LocalDeclaration Create(Context cx, LocalDeclarationStatementSyntax node, IStatementParentEntity parent, int child)
|
||||
{
|
||||
|
|
|
@ -112,6 +112,7 @@ namespace Semmle.Extraction.Kinds
|
|||
RECURSIVE_PATTERN = 115,
|
||||
PROPERTY_PATTERN = 116,
|
||||
POSITIONAL_PATTERN = 117,
|
||||
SWITCH_CASE = 118
|
||||
SWITCH_CASE = 118,
|
||||
ASSIGN_COALESCE = 119
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace Semmle.Extraction.Kinds // lgtm[cs/similar-file]
|
|||
LABEL = 27,
|
||||
CATCH = 28,
|
||||
CASE = 29,
|
||||
LOCAL_FUNCTION = 30
|
||||
LOCAL_FUNCTION = 30,
|
||||
USING_DECL = 31
|
||||
}
|
||||
}
|
||||
|
|
|
@ -903,7 +903,7 @@ class ExplicitConversionOperator extends ConversionOperator {
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
class LocalFunction extends Callable, @local_function {
|
||||
class LocalFunction extends Callable, Modifiable, @local_function {
|
||||
override string getName() { local_functions(this, result, _, _) }
|
||||
|
||||
override LocalFunction getSourceDeclaration() { local_functions(this, _, _, result) }
|
||||
|
|
|
@ -1115,40 +1115,16 @@ class LockStmt extends Stmt, @lock_stmt {
|
|||
}
|
||||
|
||||
/**
|
||||
* A `using` statement, for example
|
||||
*
|
||||
* ```
|
||||
* using (FileStream f = File.Open("settings.xml")) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
* A using block or declaration. Either a using declaration (`UsingDeclStmt`) or
|
||||
* a using block (`UsingBlockStmt`).
|
||||
*/
|
||||
class UsingStmt extends Stmt, @using_stmt {
|
||||
/** Gets the `i`th local variable of this `using` statement. */
|
||||
LocalVariable getVariable(int i) { result = this.getVariableDeclExpr(i).getVariable() }
|
||||
|
||||
/** Gets a local variable of this `using` statement. */
|
||||
LocalVariable getAVariable() { result = this.getVariable(_) }
|
||||
|
||||
/** Gets the `i`th local variable declaration of this `using` statement. */
|
||||
LocalVariableDeclExpr getVariableDeclExpr(int i) { result = this.getChild(-i - 1) }
|
||||
LocalVariableDeclExpr getVariableDeclExpr(int i) { none() }
|
||||
|
||||
/** Gets a local variable declaration of this `using` statement. */
|
||||
LocalVariableDeclExpr getAVariableDeclExpr() { result = this.getVariableDeclExpr(_) }
|
||||
|
||||
/**
|
||||
* Gets the expression directly used by this `using` statement, if any. For
|
||||
* example, `f` on line 2 in
|
||||
*
|
||||
* ```
|
||||
* var f = File.Open("settings.xml");
|
||||
* using (f) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
/**
|
||||
* Gets an expression that is used in this `using` statement. Either an
|
||||
* expression assigned to a variable, for example `File.Open("settings.xml")`
|
||||
|
@ -1169,14 +1145,69 @@ class UsingStmt extends Stmt, @using_stmt {
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
Expr getAnExpr() {
|
||||
Expr getAnExpr() { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use UsingBlockStmt.getExpr() instead.
|
||||
* Gets the expression directly used by this `using` statement, if any. For
|
||||
* example, `f` on line 2 in
|
||||
*
|
||||
* ```
|
||||
* var f = File.Open("settings.xml");
|
||||
* using (f) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
deprecated Expr getExpr() { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use UsingBlockStmt.getBody() instead.
|
||||
* Gets the body of this `using` statement.
|
||||
*/
|
||||
deprecated Stmt getBody() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `using` block statement, for example
|
||||
*
|
||||
* ```
|
||||
* using (FileStream f = File.Open("settings.xml")) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class UsingBlockStmt extends UsingStmt, @using_block_stmt {
|
||||
/** Gets the `i`th local variable of this `using` statement. */
|
||||
LocalVariable getVariable(int i) { result = this.getVariableDeclExpr(i).getVariable() }
|
||||
|
||||
/** Gets a local variable of this `using` statement. */
|
||||
LocalVariable getAVariable() { result = this.getVariable(_) }
|
||||
|
||||
/** Gets the `i`th local variable declaration of this `using` statement. */
|
||||
override LocalVariableDeclExpr getVariableDeclExpr(int i) { result = this.getChild(-i - 1) }
|
||||
|
||||
/**
|
||||
* Gets the expression directly used by this `using` statement, if any. For
|
||||
* example, `f` on line 2 in
|
||||
*
|
||||
* ```
|
||||
* var f = File.Open("settings.xml");
|
||||
* using (f) {
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
override Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
override Expr getAnExpr() {
|
||||
result = this.getAVariableDeclExpr().getInitializer()
|
||||
or
|
||||
result = this.getExpr()
|
||||
}
|
||||
|
||||
/** Gets the body of this `using` statement. */
|
||||
Stmt getBody() { result.getParent() = this }
|
||||
override Stmt getBody() { result.getParent() = this }
|
||||
|
||||
override string toString() { result = "using (...) {...}" }
|
||||
}
|
||||
|
@ -1254,6 +1285,29 @@ class LocalConstantDeclStmt extends LocalVariableDeclStmt, @const_decl_stmt {
|
|||
override string toString() { result = "const ... ...;" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `using` declaration statement, for example
|
||||
*
|
||||
* ```
|
||||
* using FileStream f = File.Open("settings.xml");
|
||||
* ```
|
||||
*/
|
||||
class UsingDeclStmt extends LocalVariableDeclStmt, UsingStmt, @using_decl_stmt {
|
||||
override string toString() { result = "using ... ...;" }
|
||||
|
||||
override LocalVariableDeclExpr getAVariableDeclExpr() {
|
||||
result = LocalVariableDeclStmt.super.getAVariableDeclExpr()
|
||||
}
|
||||
|
||||
override LocalVariableDeclExpr getVariableDeclExpr(int n) {
|
||||
result = LocalVariableDeclStmt.super.getVariableDeclExpr(n)
|
||||
}
|
||||
|
||||
override Expr getAnExpr() {
|
||||
result = this.getAVariableDeclExpr().getInitializer()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An empty statement, for example line 2 in
|
||||
*
|
||||
|
|
|
@ -468,7 +468,7 @@ module ControlFlow {
|
|||
override ControlFlowElement getChildElement(int i) {
|
||||
not this instanceof GeneralCatchClause and
|
||||
not this instanceof FixedStmt and
|
||||
not this instanceof UsingStmt and
|
||||
not this instanceof UsingBlockStmt and
|
||||
result = this.getChild(i)
|
||||
or
|
||||
this = any(GeneralCatchClause gcc | i = 0 and result = gcc.getBlock())
|
||||
|
@ -480,7 +480,7 @@ module ControlFlow {
|
|||
i = max(int j | exists(fs.getVariableDeclExpr(j))) + 1
|
||||
)
|
||||
or
|
||||
this = any(UsingStmt us |
|
||||
this = any(UsingBlockStmt us |
|
||||
if exists(us.getExpr())
|
||||
then (
|
||||
result = us.getExpr() and
|
||||
|
|
|
@ -230,3 +230,10 @@ class AddEventExpr extends AddOrRemoveEventExpr, @add_event_expr {
|
|||
class RemoveEventExpr extends AddOrRemoveEventExpr, @remove_event_expr {
|
||||
override string toString() { result = "... -= ..." }
|
||||
}
|
||||
|
||||
/**
|
||||
* A null-coalescing assignment operation, for example `x ??= y`.
|
||||
*/
|
||||
class AssignCoalesceExpr extends AssignOperation, @assign_coalesce_expr {
|
||||
override string toString() { result = "... ??= ..." }
|
||||
}
|
||||
|
|
|
@ -526,7 +526,7 @@ specific_type_parameter_constraints(
|
|||
|
||||
@modifiable = @modifiable_direct | @event_accessor;
|
||||
|
||||
@modifiable_direct = @member | @accessor;
|
||||
@modifiable_direct = @member | @accessor | @local_function;
|
||||
|
||||
modifiers(
|
||||
unique int id: @modifier,
|
||||
|
@ -798,7 +798,7 @@ case @stmt.kind of
|
|||
| 18 = @checked_stmt
|
||||
| 19 = @unchecked_stmt
|
||||
| 20 = @lock_stmt
|
||||
| 21 = @using_stmt
|
||||
| 21 = @using_block_stmt
|
||||
| 22 = @var_decl_stmt
|
||||
| 23 = @const_decl_stmt
|
||||
| 24 = @empty_stmt
|
||||
|
@ -808,11 +808,14 @@ case @stmt.kind of
|
|||
| 28 = @catch
|
||||
| 29 = @case_stmt
|
||||
| 30 = @local_function_stmt
|
||||
| 31 = @using_decl_stmt
|
||||
;
|
||||
|
||||
@using_stmt = @using_block_stmt | @using_decl_stmt;
|
||||
|
||||
@labeled_stmt = @label_stmt | @case;
|
||||
|
||||
@decl_stmt = @var_decl_stmt | @const_decl_stmt;
|
||||
@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
|
||||
|
||||
@cond_stmt = @if_stmt | @switch_stmt;
|
||||
|
||||
|
@ -983,6 +986,7 @@ case @expr.kind of
|
|||
| 116 = @property_pattern_expr
|
||||
| 117 = @positional_pattern_expr
|
||||
| 118 = @switch_case_expr
|
||||
| 119 = @assign_coalesce_expr
|
||||
;
|
||||
|
||||
@switch = @switch_stmt | @switch_expr;
|
||||
|
@ -995,7 +999,7 @@ case @expr.kind of
|
|||
| @string_literal_expr | @null_literal_expr;
|
||||
|
||||
@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
|
||||
@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr;
|
||||
@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
|
||||
@assign_event_expr = @add_event_expr | @remove_event_expr;
|
||||
|
||||
@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
|
||||
|
|
|
@ -360,10 +360,14 @@
|
|||
<v>1854</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@using_stmt</k>
|
||||
<k>@using_block_stmt</k>
|
||||
<v>5815</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@using_decl_stmt</k>
|
||||
<v>1000</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@var_decl_stmt</k>
|
||||
<v>243866</v>
|
||||
</e>
|
||||
|
@ -688,6 +692,10 @@
|
|||
<v>116</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@assign_coalesce_expr</k>
|
||||
<v>116</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>@object_init_expr</k>
|
||||
<v>5320</v>
|
||||
</e>
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
| Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:132:13:132:13 | x | read |
|
||||
| Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:132:13:132:13 | x | write |
|
||||
| Assignables.cs:133:29:133:29 | String s | Assignables.cs:133:29:133:29 | s | write |
|
||||
| Assignables.cs:138:19:138:19 | access to local variable x | Assignables.cs:138:19:138:19 | x | write |
|
||||
| Discards.cs:7:9:7:9 | access to parameter x | Discards.cs:5:30:5:30 | x | write |
|
||||
| Discards.cs:20:32:20:32 | Boolean z | Discards.cs:20:32:20:32 | z | write |
|
||||
| Discards.cs:25:27:25:30 | access to parameter args | Discards.cs:23:27:23:30 | args | read |
|
||||
|
|
|
@ -87,6 +87,7 @@
|
|||
| Assignables.cs:132:13:132:13 | x | Assignables.cs:132:13:132:17 | Int32 x = ... | Assignables.cs:132:13:132:13 | access to local variable x | Assignables.cs:132:17:132:17 | 0 | certain |
|
||||
| Assignables.cs:132:13:132:13 | x | Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:133:15:133:15 | <none> | certain |
|
||||
| Assignables.cs:133:29:133:29 | s | Assignables.cs:133:29:133:29 | String s | Assignables.cs:133:29:133:29 | String s | Assignables.cs:133:29:133:29 | <none> | certain |
|
||||
| Assignables.cs:138:19:138:19 | x | Assignables.cs:138:19:138:50 | MemoryStream x = ... | Assignables.cs:138:19:138:19 | access to local variable x | Assignables.cs:138:23:138:50 | object creation of type MemoryStream | certain |
|
||||
| Discards.cs:5:30:5:30 | x | Discards.cs:5:30:5:30 | x | Discards.cs:5:30:5:30 | <none> | Discards.cs:5:30:5:30 | <none> | certain |
|
||||
| Discards.cs:5:30:5:30 | x | Discards.cs:7:9:7:17 | ... = ... | Discards.cs:7:9:7:9 | access to parameter x | Discards.cs:7:13:7:17 | false | certain |
|
||||
| Discards.cs:19:14:19:14 | x | Discards.cs:19:9:19:29 | ... = ... | Discards.cs:19:9:19:29 | <none> | Discards.cs:19:9:19:29 | <none> | certain |
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
| Assignables.cs:132:13:132:17 | Int32 x = ... | Assignables.cs:132:13:132:17 | Int32 x = ... |
|
||||
| Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:133:9:133:30 | delegate call |
|
||||
| Assignables.cs:133:29:133:29 | String s | Assignables.cs:133:9:133:30 | delegate call |
|
||||
| Assignables.cs:138:19:138:50 | MemoryStream x = ... | Assignables.cs:138:19:138:50 | MemoryStream x = ... |
|
||||
| Discards.cs:5:30:5:30 | x | Discards.cs:5:19:5:19 | enter f |
|
||||
| Discards.cs:7:9:7:17 | ... = ... | Discards.cs:7:9:7:17 | ... = ... |
|
||||
| Discards.cs:13:9:13:20 | ... = ... | Discards.cs:13:9:13:20 | ... = ... |
|
||||
|
|
|
@ -132,4 +132,11 @@ class Assignables
|
|||
var x = 0;
|
||||
d(ref x, out string s);
|
||||
}
|
||||
|
||||
void UsingDeclarations()
|
||||
{
|
||||
using var x = new System.IO.MemoryStream();
|
||||
}
|
||||
}
|
||||
|
||||
// semmle-extractor-options: /langversion:8.0
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
| Assignables.cs:130:31:130:31 | d |
|
||||
| Assignables.cs:132:13:132:13 | x |
|
||||
| Assignables.cs:133:29:133:29 | s |
|
||||
| Assignables.cs:138:19:138:19 | x |
|
||||
| Discards.cs:5:6:5:8 | Item1 |
|
||||
| Discards.cs:5:11:5:16 | Item2 |
|
||||
| Discards.cs:5:30:5:30 | x |
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
| Assignables.cs:125:13:125:13 | s | Assignables.cs:125:17:125:25 | nameof(...) |
|
||||
| Assignables.cs:125:13:125:13 | s | Assignables.cs:126:13:126:30 | nameof(...) |
|
||||
| Assignables.cs:132:13:132:13 | x | Assignables.cs:132:17:132:17 | 0 |
|
||||
| Assignables.cs:138:19:138:19 | x | Assignables.cs:138:23:138:50 | object creation of type MemoryStream |
|
||||
| Discards.cs:5:30:5:30 | x | Discards.cs:7:13:7:17 | false |
|
||||
| Finally.cs:7:13:7:13 | i | Finally.cs:7:17:7:17 | 0 |
|
||||
| Finally.cs:7:13:7:13 | i | Finally.cs:15:17:15:17 | 1 |
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
|
||||
class NullCoalescingAssignment
|
||||
{
|
||||
void NullCoalescing()
|
||||
{
|
||||
object o = null;
|
||||
o ??= this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
nullcoalescing
|
||||
| NullCoalescingAssignment.cs:8:9:8:18 | ... ?? ... |
|
||||
assignments
|
||||
| NullCoalescingAssignment.cs:8:9:8:18 | ... ??= ... | NullCoalescingAssignment.cs:8:9:8:18 | ... = ... |
|
|
@ -0,0 +1,7 @@
|
|||
import csharp
|
||||
|
||||
query predicate nullcoalescing(NullCoalescingExpr expr) { any() }
|
||||
|
||||
query predicate assignments(AssignCoalesceExpr expr, Expr expanded) {
|
||||
expanded = expr.getExpandedAssignment()
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
| NullCoalescingAssignment.cs:5:10:5:23 | enter NullCoalescing | NullCoalescingAssignment.cs:6:5:9:5 | {...} | semmle.label | successor |
|
||||
| NullCoalescingAssignment.cs:6:5:9:5 | {...} | NullCoalescingAssignment.cs:7:9:7:24 | ... ...; | semmle.label | successor |
|
||||
| NullCoalescingAssignment.cs:7:9:7:24 | ... ...; | NullCoalescingAssignment.cs:7:20:7:23 | null | semmle.label | successor |
|
||||
| NullCoalescingAssignment.cs:7:16:7:23 | Object o = ... | NullCoalescingAssignment.cs:8:9:8:19 | ...; | semmle.label | successor |
|
||||
| NullCoalescingAssignment.cs:7:20:7:23 | null | NullCoalescingAssignment.cs:7:16:7:23 | Object o = ... | semmle.label | successor |
|
||||
| NullCoalescingAssignment.cs:8:9:8:9 | access to local variable o | NullCoalescingAssignment.cs:8:9:8:18 | ... = ... | semmle.label | non-null |
|
||||
| NullCoalescingAssignment.cs:8:9:8:9 | access to local variable o | NullCoalescingAssignment.cs:8:15:8:18 | this access | semmle.label | null |
|
||||
| NullCoalescingAssignment.cs:8:9:8:18 | ... = ... | NullCoalescingAssignment.cs:5:10:5:23 | exit NullCoalescing | semmle.label | successor |
|
||||
| NullCoalescingAssignment.cs:8:9:8:18 | ... ?? ... | NullCoalescingAssignment.cs:8:9:8:9 | access to local variable o | semmle.label | successor |
|
||||
| NullCoalescingAssignment.cs:8:9:8:19 | ...; | NullCoalescingAssignment.cs:8:9:8:18 | ... ?? ... | semmle.label | successor |
|
||||
| NullCoalescingAssignment.cs:8:15:8:18 | this access | NullCoalescingAssignment.cs:8:9:8:18 | ... = ... | semmle.label | successor |
|
|
@ -0,0 +1,10 @@
|
|||
import csharp
|
||||
import semmle.code.csharp.controlflow.ControlFlowGraph
|
||||
|
||||
query predicate edges(ControlFlow::Node node1, ControlFlow::Node node2, string label, string value) {
|
||||
label = "semmle.label" and
|
||||
exists(ControlFlow::SuccessorType t |
|
||||
node2 = node1.getASuccessorByType(t) and value = t.toString()
|
||||
)
|
||||
and node1.getEnclosingCallable().hasName("NullCoalescing")
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
using System;
|
||||
|
||||
class StaticLocalFunction
|
||||
{
|
||||
int F()
|
||||
{
|
||||
static int G(int x) => x;
|
||||
return G(12);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// semmle-extractor-options: /langversion:8.0
|
||||
|
||||
using System;
|
||||
|
||||
class StaticLocalFunctions
|
||||
{
|
||||
int Fn(int x)
|
||||
{
|
||||
static int I(int y) => y;
|
||||
int J(int y) => x+y;
|
||||
return I(x) + J(x);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
| StaticLocalFunctions.cs:9:9:9:33 | I | static |
|
|
@ -0,0 +1,5 @@
|
|||
import csharp
|
||||
|
||||
from LocalFunction fn, string modifier
|
||||
where fn.hasModifier(modifier)
|
||||
select fn, modifier
|
|
@ -0,0 +1,26 @@
|
|||
| UsingDeclarations.cs:6:10:6:30 | enter TestUsingDeclarations | UsingDeclarations.cs:7:5:16:5 | {...} | semmle.label | successor |
|
||||
| UsingDeclarations.cs:7:5:16:5 | {...} | UsingDeclarations.cs:8:9:8:116 | using ... ...; | semmle.label | successor |
|
||||
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | UsingDeclarations.cs:8:49:8:53 | "..." | semmle.label | successor |
|
||||
| UsingDeclarations.cs:8:26:8:69 | FileStream file1 = ... | UsingDeclarations.cs:8:95:8:99 | "..." | semmle.label | successor |
|
||||
| UsingDeclarations.cs:8:34:8:69 | object creation of type FileStream | UsingDeclarations.cs:8:26:8:69 | FileStream file1 = ... | semmle.label | successor |
|
||||
| UsingDeclarations.cs:8:49:8:53 | "..." | UsingDeclarations.cs:8:56:8:68 | access to constant Open | semmle.label | successor |
|
||||
| UsingDeclarations.cs:8:56:8:68 | access to constant Open | UsingDeclarations.cs:8:34:8:69 | object creation of type FileStream | semmle.label | successor |
|
||||
| UsingDeclarations.cs:8:72:8:115 | FileStream file2 = ... | UsingDeclarations.cs:10:9:12:9 | using (...) {...} | semmle.label | successor |
|
||||
| UsingDeclarations.cs:8:80:8:115 | object creation of type FileStream | UsingDeclarations.cs:8:72:8:115 | FileStream file2 = ... | semmle.label | successor |
|
||||
| UsingDeclarations.cs:8:95:8:99 | "..." | UsingDeclarations.cs:8:102:8:114 | access to constant Open | semmle.label | successor |
|
||||
| UsingDeclarations.cs:8:102:8:114 | access to constant Open | UsingDeclarations.cs:8:80:8:115 | object creation of type FileStream | semmle.label | successor |
|
||||
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} | UsingDeclarations.cs:10:49:10:53 | "..." | semmle.label | successor |
|
||||
| UsingDeclarations.cs:10:26:10:69 | FileStream file3 = ... | UsingDeclarations.cs:10:95:10:99 | "..." | semmle.label | successor |
|
||||
| UsingDeclarations.cs:10:34:10:69 | object creation of type FileStream | UsingDeclarations.cs:10:26:10:69 | FileStream file3 = ... | semmle.label | successor |
|
||||
| UsingDeclarations.cs:10:49:10:53 | "..." | UsingDeclarations.cs:10:56:10:68 | access to constant Open | semmle.label | successor |
|
||||
| UsingDeclarations.cs:10:56:10:68 | access to constant Open | UsingDeclarations.cs:10:34:10:69 | object creation of type FileStream | semmle.label | successor |
|
||||
| UsingDeclarations.cs:10:72:10:115 | FileStream file4 = ... | UsingDeclarations.cs:11:9:12:9 | {...} | semmle.label | successor |
|
||||
| UsingDeclarations.cs:10:80:10:115 | object creation of type FileStream | UsingDeclarations.cs:10:72:10:115 | FileStream file4 = ... | semmle.label | successor |
|
||||
| UsingDeclarations.cs:10:95:10:99 | "..." | UsingDeclarations.cs:10:102:10:114 | access to constant Open | semmle.label | successor |
|
||||
| UsingDeclarations.cs:10:102:10:114 | access to constant Open | UsingDeclarations.cs:10:80:10:115 | object creation of type FileStream | semmle.label | successor |
|
||||
| UsingDeclarations.cs:11:9:12:9 | {...} | UsingDeclarations.cs:14:9:15:13 | using (...) {...} | semmle.label | successor |
|
||||
| UsingDeclarations.cs:14:9:15:13 | using (...) {...} | UsingDeclarations.cs:14:30:14:34 | "..." | semmle.label | successor |
|
||||
| UsingDeclarations.cs:14:15:14:50 | object creation of type FileStream | UsingDeclarations.cs:15:13:15:13 | ; | semmle.label | successor |
|
||||
| UsingDeclarations.cs:14:30:14:34 | "..." | UsingDeclarations.cs:14:37:14:49 | access to constant Open | semmle.label | successor |
|
||||
| UsingDeclarations.cs:14:37:14:49 | access to constant Open | UsingDeclarations.cs:14:15:14:50 | object creation of type FileStream | semmle.label | successor |
|
||||
| UsingDeclarations.cs:15:13:15:13 | ; | UsingDeclarations.cs:6:10:6:30 | exit TestUsingDeclarations | semmle.label | successor |
|
|
@ -0,0 +1,10 @@
|
|||
import csharp
|
||||
import semmle.code.csharp.controlflow.ControlFlowGraph
|
||||
|
||||
query predicate edges(ControlFlow::Node node1, ControlFlow::Node node2, string label, string value) {
|
||||
label = "semmle.label" and
|
||||
exists(ControlFlow::SuccessorType t |
|
||||
node2 = node1.getASuccessorByType(t) and value = t.toString()
|
||||
)
|
||||
and node1.getEnclosingCallable().hasName("TestUsingDeclarations")
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
class UsingDeclarations
|
||||
{
|
||||
void TestUsingDeclarations()
|
||||
{
|
||||
using FileStream file1 = new FileStream("...", FileMode.Open), file2 = new FileStream("...", FileMode.Open);
|
||||
|
||||
using(FileStream file3 = new FileStream("...", FileMode.Open), file4 = new FileStream("...", FileMode.Open))
|
||||
{
|
||||
}
|
||||
|
||||
using(new FileStream("...", FileMode.Open))
|
||||
;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
localVars
|
||||
| UsingDeclarations.cs:8:26:8:30 | file1 |
|
||||
| UsingDeclarations.cs:8:72:8:76 | file2 |
|
||||
| UsingDeclarations.cs:10:26:10:30 | file3 |
|
||||
| UsingDeclarations.cs:10:72:10:76 | file4 |
|
||||
localVariableDeclarations
|
||||
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 0 | UsingDeclarations.cs:8:26:8:69 | FileStream file1 = ... |
|
||||
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 1 | UsingDeclarations.cs:8:72:8:115 | FileStream file2 = ... |
|
||||
usingStmts1
|
||||
| UsingDeclarations.cs:8:9:8:116 | using ... ...; |
|
||||
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} |
|
||||
| UsingDeclarations.cs:14:9:15:13 | using (...) {...} |
|
||||
usingStmts
|
||||
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 0 | UsingDeclarations.cs:8:26:8:69 | FileStream file1 = ... |
|
||||
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 1 | UsingDeclarations.cs:8:72:8:115 | FileStream file2 = ... |
|
||||
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} | 0 | UsingDeclarations.cs:10:26:10:69 | FileStream file3 = ... |
|
||||
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} | 1 | UsingDeclarations.cs:10:72:10:115 | FileStream file4 = ... |
|
||||
usingDecls
|
||||
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 0 | UsingDeclarations.cs:8:26:8:69 | FileStream file1 = ... |
|
||||
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | 1 | UsingDeclarations.cs:8:72:8:115 | FileStream file2 = ... |
|
||||
usingExprs
|
||||
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | UsingDeclarations.cs:8:34:8:69 | object creation of type FileStream |
|
||||
| UsingDeclarations.cs:8:9:8:116 | using ... ...; | UsingDeclarations.cs:8:80:8:115 | object creation of type FileStream |
|
||||
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} | UsingDeclarations.cs:10:34:10:69 | object creation of type FileStream |
|
||||
| UsingDeclarations.cs:10:9:12:9 | using (...) {...} | UsingDeclarations.cs:10:80:10:115 | object creation of type FileStream |
|
||||
| UsingDeclarations.cs:14:9:15:13 | using (...) {...} | UsingDeclarations.cs:14:15:14:50 | object creation of type FileStream |
|
|
@ -0,0 +1,22 @@
|
|||
import csharp
|
||||
|
||||
query predicate localVars(LocalVariable decl) {
|
||||
decl.getEnclosingCallable().hasName("TestUsingDeclarations")
|
||||
}
|
||||
|
||||
query predicate localVariableDeclarations(
|
||||
LocalVariableDeclStmt stmt, int i, LocalVariableDeclExpr decl
|
||||
) {
|
||||
decl.getEnclosingCallable().hasName("TestUsingDeclarations") and
|
||||
decl = stmt.getVariableDeclExpr(i)
|
||||
}
|
||||
|
||||
query predicate usingStmts1(UsingStmt stmt) { any() }
|
||||
|
||||
query predicate usingStmts(UsingStmt stmt, int i, LocalVariableDeclExpr decl) {
|
||||
decl = stmt.getVariableDeclExpr(i)
|
||||
}
|
||||
|
||||
query predicate usingDecls(UsingDeclStmt stmt, int i, Expr e) { e = stmt.getChild(i) }
|
||||
|
||||
query predicate usingExprs(UsingStmt stmt, Expr e) { e = stmt.getAnExpr() }
|
|
@ -5,7 +5,7 @@
|
|||
import csharp
|
||||
|
||||
where
|
||||
forall(UsingStmt s |
|
||||
forall(UsingBlockStmt s |
|
||||
exists(s.getAnExpr()) and
|
||||
exists(s.getBody())
|
||||
)
|
||||
|
|
|
@ -58,6 +58,10 @@ class Test
|
|||
SqlConnection c1f = new SqlConnection();
|
||||
Throw2(c1f);
|
||||
c1f.Dispose();
|
||||
|
||||
// GOOD: using declaration
|
||||
using SqlConnection c2 = new SqlConnection("");
|
||||
c2.Open();
|
||||
}
|
||||
|
||||
void Throw1(SqlConnection sc)
|
||||
|
@ -71,3 +75,5 @@ class Test
|
|||
return sc == null ? throw new Exception() : sc;
|
||||
}
|
||||
}
|
||||
|
||||
// semmle-extractor-options: /langversion:8.0
|
||||
|
|
|
@ -78,6 +78,9 @@ class Test
|
|||
// GOOD: Passed to a library. This is only detected in CIL.
|
||||
Console.SetOut(new StreamWriter("output.txt"));
|
||||
|
||||
// GOOD: Disposed automatically.
|
||||
using var c2 = new Timer(TimerProc);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -88,3 +91,5 @@ class Test
|
|||
{
|
||||
}
|
||||
}
|
||||
|
||||
// semmle-extractor-options: /langversion:8.0
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,2 @@
|
|||
description: Support for null-coalescing assignment, static local functions, and using declarations.
|
||||
compatibility: backwards
|
Загрузка…
Ссылка в новой задаче