зеркало из 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:
|
* The following C# 8 features are now extracted:
|
||||||
- Range expressions
|
- Range expressions
|
||||||
- Recursive patterns
|
- Recursive patterns
|
||||||
|
- Using declaration statements
|
||||||
|
- `static` modifiers on local functions
|
||||||
|
- Null-coalescing assignment expressions
|
||||||
|
|
||||||
* The `unmanaged` type parameter constraint is now extracted.
|
* The `unmanaged` type parameter constraint is now extracted.
|
||||||
|
|
||||||
## Changes to QL libraries
|
## 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 `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 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:
|
* 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 `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 `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`.
|
- 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`
|
- Classes `IsConstantExpr`, `IsTypeExpr` and `IsPatternExpr` are deprecated in favour of `IsExpr`
|
||||||
- Class `Switch` models both `SwitchExpr` and `SwitchStmt`
|
- Class `Switch` models both `SwitchExpr` and `SwitchStmt`
|
||||||
- Class `Case` models both `CaseStmt` and `SwitchCaseExpr`
|
- Class `Case` models both `CaseStmt` and `SwitchCaseExpr`
|
||||||
|
- Class `UsingStmt` models both `UsingBlockStmt` and `UsingDeclStmt`
|
||||||
|
|
||||||
## Changes to autobuilder
|
## Changes to autobuilder
|
||||||
|
|
|
@ -71,6 +71,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||||
return ExprKind.ASSIGN_LSHIFT;
|
return ExprKind.ASSIGN_LSHIFT;
|
||||||
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
|
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
|
||||||
return ExprKind.ASSIGN_RSHIFT;
|
return ExprKind.ASSIGN_RSHIFT;
|
||||||
|
case SyntaxKind.QuestionQuestionEqualsToken:
|
||||||
|
return ExprKind.ASSIGN_COALESCE;
|
||||||
default:
|
default:
|
||||||
cx.ModelError(syntax, "Unrecognised assignment type " + GetKind(cx, syntax));
|
cx.ModelError(syntax, "Unrecognised assignment type " + GetKind(cx, syntax));
|
||||||
return ExprKind.UNKNOWN;
|
return ExprKind.UNKNOWN;
|
||||||
|
@ -142,6 +144,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||||
return ExprKind.SUB;
|
return ExprKind.SUB;
|
||||||
case ExprKind.ASSIGN_XOR:
|
case ExprKind.ASSIGN_XOR:
|
||||||
return ExprKind.BIT_XOR;
|
return ExprKind.BIT_XOR;
|
||||||
|
case ExprKind.ASSIGN_COALESCE:
|
||||||
|
return ExprKind.NULL_COALESCING;
|
||||||
default:
|
default:
|
||||||
cx.ModelError(Syntax, "Couldn't unfold assignment of type " + kind);
|
cx.ModelError(Syntax, "Couldn't unfold assignment of type " + kind);
|
||||||
return ExprKind.UNKNOWN;
|
return ExprKind.UNKNOWN;
|
||||||
|
|
|
@ -80,6 +80,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||||
case SyntaxKind.RightShiftAssignmentExpression:
|
case SyntaxKind.RightShiftAssignmentExpression:
|
||||||
case SyntaxKind.DivideAssignmentExpression:
|
case SyntaxKind.DivideAssignmentExpression:
|
||||||
case SyntaxKind.ModuloAssignmentExpression:
|
case SyntaxKind.ModuloAssignmentExpression:
|
||||||
|
case SyntaxKind.CoalesceAssignmentExpression:
|
||||||
return Assignment.Create(info);
|
return Assignment.Create(info);
|
||||||
|
|
||||||
case SyntaxKind.ObjectCreationExpression:
|
case SyntaxKind.ObjectCreationExpression:
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Semmle.Extraction.CSharp.Entities
|
namespace Semmle.Extraction.CSharp.Entities
|
||||||
{
|
{
|
||||||
|
@ -39,6 +41,18 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||||
public override void Populate()
|
public override void Populate()
|
||||||
{
|
{
|
||||||
PopulateMethod();
|
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 originalDefinition = IsSourceDeclaration ? this : Create(Context, symbol.OriginalDefinition);
|
||||||
var returnType = Type.Create(Context, symbol.ReturnType);
|
var returnType = Type.Create(Context, symbol.ReturnType);
|
||||||
Context.Emit(Tuples.local_functions(this, symbol.Name, returnType, originalDefinition));
|
Context.Emit(Tuples.local_functions(this, symbol.Name, returnType, originalDefinition));
|
||||||
|
|
|
@ -6,8 +6,19 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
|
||||||
{
|
{
|
||||||
class LocalDeclaration : Statement<LocalDeclarationStatementSyntax>
|
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)
|
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)
|
public static LocalDeclaration Create(Context cx, LocalDeclarationStatementSyntax node, IStatementParentEntity parent, int child)
|
||||||
{
|
{
|
||||||
|
|
|
@ -112,6 +112,7 @@ namespace Semmle.Extraction.Kinds
|
||||||
RECURSIVE_PATTERN = 115,
|
RECURSIVE_PATTERN = 115,
|
||||||
PROPERTY_PATTERN = 116,
|
PROPERTY_PATTERN = 116,
|
||||||
POSITIONAL_PATTERN = 117,
|
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,
|
LABEL = 27,
|
||||||
CATCH = 28,
|
CATCH = 28,
|
||||||
CASE = 29,
|
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 string getName() { local_functions(this, result, _, _) }
|
||||||
|
|
||||||
override LocalFunction getSourceDeclaration() { 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
|
* A using block or declaration. Either a using declaration (`UsingDeclStmt`) or
|
||||||
*
|
* a using block (`UsingBlockStmt`).
|
||||||
* ```
|
|
||||||
* using (FileStream f = File.Open("settings.xml")) {
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
class UsingStmt extends Stmt, @using_stmt {
|
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. */
|
/** 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. */
|
/** Gets a local variable declaration of this `using` statement. */
|
||||||
LocalVariableDeclExpr getAVariableDeclExpr() { result = this.getVariableDeclExpr(_) }
|
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
|
* Gets an expression that is used in this `using` statement. Either an
|
||||||
* expression assigned to a variable, for example `File.Open("settings.xml")`
|
* 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()
|
result = this.getAVariableDeclExpr().getInitializer()
|
||||||
or
|
or
|
||||||
result = this.getExpr()
|
result = this.getExpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the body of this `using` statement. */
|
/** Gets the body of this `using` statement. */
|
||||||
Stmt getBody() { result.getParent() = this }
|
override Stmt getBody() { result.getParent() = this }
|
||||||
|
|
||||||
override string toString() { result = "using (...) {...}" }
|
override string toString() { result = "using (...) {...}" }
|
||||||
}
|
}
|
||||||
|
@ -1254,6 +1285,29 @@ class LocalConstantDeclStmt extends LocalVariableDeclStmt, @const_decl_stmt {
|
||||||
override string toString() { result = "const ... ...;" }
|
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
|
* An empty statement, for example line 2 in
|
||||||
*
|
*
|
||||||
|
|
|
@ -468,7 +468,7 @@ module ControlFlow {
|
||||||
override ControlFlowElement getChildElement(int i) {
|
override ControlFlowElement getChildElement(int i) {
|
||||||
not this instanceof GeneralCatchClause and
|
not this instanceof GeneralCatchClause and
|
||||||
not this instanceof FixedStmt and
|
not this instanceof FixedStmt and
|
||||||
not this instanceof UsingStmt and
|
not this instanceof UsingBlockStmt and
|
||||||
result = this.getChild(i)
|
result = this.getChild(i)
|
||||||
or
|
or
|
||||||
this = any(GeneralCatchClause gcc | i = 0 and result = gcc.getBlock())
|
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
|
i = max(int j | exists(fs.getVariableDeclExpr(j))) + 1
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
this = any(UsingStmt us |
|
this = any(UsingBlockStmt us |
|
||||||
if exists(us.getExpr())
|
if exists(us.getExpr())
|
||||||
then (
|
then (
|
||||||
result = us.getExpr() and
|
result = us.getExpr() and
|
||||||
|
|
|
@ -230,3 +230,10 @@ class AddEventExpr extends AddOrRemoveEventExpr, @add_event_expr {
|
||||||
class RemoveEventExpr extends AddOrRemoveEventExpr, @remove_event_expr {
|
class RemoveEventExpr extends AddOrRemoveEventExpr, @remove_event_expr {
|
||||||
override string toString() { result = "... -= ..." }
|
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 = @modifiable_direct | @event_accessor;
|
||||||
|
|
||||||
@modifiable_direct = @member | @accessor;
|
@modifiable_direct = @member | @accessor | @local_function;
|
||||||
|
|
||||||
modifiers(
|
modifiers(
|
||||||
unique int id: @modifier,
|
unique int id: @modifier,
|
||||||
|
@ -798,7 +798,7 @@ case @stmt.kind of
|
||||||
| 18 = @checked_stmt
|
| 18 = @checked_stmt
|
||||||
| 19 = @unchecked_stmt
|
| 19 = @unchecked_stmt
|
||||||
| 20 = @lock_stmt
|
| 20 = @lock_stmt
|
||||||
| 21 = @using_stmt
|
| 21 = @using_block_stmt
|
||||||
| 22 = @var_decl_stmt
|
| 22 = @var_decl_stmt
|
||||||
| 23 = @const_decl_stmt
|
| 23 = @const_decl_stmt
|
||||||
| 24 = @empty_stmt
|
| 24 = @empty_stmt
|
||||||
|
@ -808,11 +808,14 @@ case @stmt.kind of
|
||||||
| 28 = @catch
|
| 28 = @catch
|
||||||
| 29 = @case_stmt
|
| 29 = @case_stmt
|
||||||
| 30 = @local_function_stmt
|
| 30 = @local_function_stmt
|
||||||
|
| 31 = @using_decl_stmt
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@using_stmt = @using_block_stmt | @using_decl_stmt;
|
||||||
|
|
||||||
@labeled_stmt = @label_stmt | @case;
|
@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;
|
@cond_stmt = @if_stmt | @switch_stmt;
|
||||||
|
|
||||||
|
@ -983,6 +986,7 @@ case @expr.kind of
|
||||||
| 116 = @property_pattern_expr
|
| 116 = @property_pattern_expr
|
||||||
| 117 = @positional_pattern_expr
|
| 117 = @positional_pattern_expr
|
||||||
| 118 = @switch_case_expr
|
| 118 = @switch_case_expr
|
||||||
|
| 119 = @assign_coalesce_expr
|
||||||
;
|
;
|
||||||
|
|
||||||
@switch = @switch_stmt | @switch_expr;
|
@switch = @switch_stmt | @switch_expr;
|
||||||
|
@ -995,7 +999,7 @@ case @expr.kind of
|
||||||
| @string_literal_expr | @null_literal_expr;
|
| @string_literal_expr | @null_literal_expr;
|
||||||
|
|
||||||
@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_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_event_expr = @add_event_expr | @remove_event_expr;
|
||||||
|
|
||||||
@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
|
@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
|
||||||
|
|
|
@ -360,10 +360,14 @@
|
||||||
<v>1854</v>
|
<v>1854</v>
|
||||||
</e>
|
</e>
|
||||||
<e>
|
<e>
|
||||||
<k>@using_stmt</k>
|
<k>@using_block_stmt</k>
|
||||||
<v>5815</v>
|
<v>5815</v>
|
||||||
</e>
|
</e>
|
||||||
<e>
|
<e>
|
||||||
|
<k>@using_decl_stmt</k>
|
||||||
|
<v>1000</v>
|
||||||
|
</e>
|
||||||
|
<e>
|
||||||
<k>@var_decl_stmt</k>
|
<k>@var_decl_stmt</k>
|
||||||
<v>243866</v>
|
<v>243866</v>
|
||||||
</e>
|
</e>
|
||||||
|
@ -688,6 +692,10 @@
|
||||||
<v>116</v>
|
<v>116</v>
|
||||||
</e>
|
</e>
|
||||||
<e>
|
<e>
|
||||||
|
<k>@assign_coalesce_expr</k>
|
||||||
|
<v>116</v>
|
||||||
|
</e>
|
||||||
|
<e>
|
||||||
<k>@object_init_expr</k>
|
<k>@object_init_expr</k>
|
||||||
<v>5320</v>
|
<v>5320</v>
|
||||||
</e>
|
</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 | read |
|
||||||
| Assignables.cs:133:15:133:15 | access to local variable x | Assignables.cs:132:13:132:13 | x | write |
|
| 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: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: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: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 |
|
| 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: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: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: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: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: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 |
|
| 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: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: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: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: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:7:9:7:17 | ... = ... | Discards.cs:7:9:7:17 | ... = ... |
|
||||||
| Discards.cs:13:9:13:20 | ... = ... | Discards.cs:13:9:13:20 | ... = ... |
|
| Discards.cs:13:9:13:20 | ... = ... | Discards.cs:13:9:13:20 | ... = ... |
|
||||||
|
|
|
@ -132,4 +132,11 @@ class Assignables
|
||||||
var x = 0;
|
var x = 0;
|
||||||
d(ref x, out string s);
|
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:130:31:130:31 | d |
|
||||||
| Assignables.cs:132:13:132:13 | x |
|
| Assignables.cs:132:13:132:13 | x |
|
||||||
| Assignables.cs:133:29:133:29 | s |
|
| Assignables.cs:133:29:133:29 | s |
|
||||||
|
| Assignables.cs:138:19:138:19 | x |
|
||||||
| Discards.cs:5:6:5:8 | Item1 |
|
| Discards.cs:5:6:5:8 | Item1 |
|
||||||
| Discards.cs:5:11:5:16 | Item2 |
|
| Discards.cs:5:11:5:16 | Item2 |
|
||||||
| Discards.cs:5:30:5:30 | x |
|
| 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:125:17:125:25 | nameof(...) |
|
||||||
| Assignables.cs:125:13:125:13 | s | Assignables.cs:126:13:126:30 | 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: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 |
|
| 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:7:17:7:17 | 0 |
|
||||||
| Finally.cs:7:13:7:13 | i | Finally.cs:15:17:15:17 | 1 |
|
| 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
|
import csharp
|
||||||
|
|
||||||
where
|
where
|
||||||
forall(UsingStmt s |
|
forall(UsingBlockStmt s |
|
||||||
exists(s.getAnExpr()) and
|
exists(s.getAnExpr()) and
|
||||||
exists(s.getBody())
|
exists(s.getBody())
|
||||||
)
|
)
|
||||||
|
|
|
@ -58,6 +58,10 @@ class Test
|
||||||
SqlConnection c1f = new SqlConnection();
|
SqlConnection c1f = new SqlConnection();
|
||||||
Throw2(c1f);
|
Throw2(c1f);
|
||||||
c1f.Dispose();
|
c1f.Dispose();
|
||||||
|
|
||||||
|
// GOOD: using declaration
|
||||||
|
using SqlConnection c2 = new SqlConnection("");
|
||||||
|
c2.Open();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Throw1(SqlConnection sc)
|
void Throw1(SqlConnection sc)
|
||||||
|
@ -71,3 +75,5 @@ class Test
|
||||||
return sc == null ? throw new Exception() : sc;
|
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.
|
// GOOD: Passed to a library. This is only detected in CIL.
|
||||||
Console.SetOut(new StreamWriter("output.txt"));
|
Console.SetOut(new StreamWriter("output.txt"));
|
||||||
|
|
||||||
|
// GOOD: Disposed automatically.
|
||||||
|
using var c2 = new Timer(TimerProc);
|
||||||
|
|
||||||
return null;
|
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
|
Загрузка…
Ссылка в новой задаче