mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
Rework foreach_stmt_info extraction
This commit is contained in:
@@ -8,6 +8,15 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
|
||||
{
|
||||
internal class ForEach : Statement<ForEachStatementSyntax>
|
||||
{
|
||||
internal enum ForeachSymbolType
|
||||
{
|
||||
GetEnumeratorMethod = 1,
|
||||
CurrentProperty,
|
||||
MoveNextMethod,
|
||||
DisposeMethod,
|
||||
ElementType
|
||||
}
|
||||
|
||||
private ForEach(Context cx, ForEachStatementSyntax stmt, IStatementParentEntity parent, int child)
|
||||
: base(cx, stmt, StmtKind.FOREACH, parent, child) { }
|
||||
|
||||
@@ -33,13 +42,44 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
|
||||
Statement.Create(cx, Stmt.Statement, this, 2);
|
||||
|
||||
var info = semanticModel.GetForEachStatementInfo(Stmt);
|
||||
var getEnumerator = Method.Create(cx, info.GetEnumeratorMethod);
|
||||
var currentProp = Property.Create(cx, info.CurrentProperty);
|
||||
var moveNext = Method.Create(cx, info.MoveNextMethod);
|
||||
var dispose = Method.Create(cx, info.DisposeMethod);
|
||||
var elementType = Type.Create(cx, info.ElementType);
|
||||
|
||||
trapFile.foreach_stmt_info(this, elementType, getEnumerator, moveNext, dispose, currentProp, info.IsAsynchronous);
|
||||
if (info.Equals(default))
|
||||
{
|
||||
cx.ExtractionError("Could not get foreach statement info", null, Location.Create(cx, this.ReportingLocation), severity: Util.Logging.Severity.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
trapFile.foreach_stmt_info(this, info.IsAsynchronous);
|
||||
|
||||
if (info.GetEnumeratorMethod != null)
|
||||
{
|
||||
var m = Method.Create(cx, info.GetEnumeratorMethod);
|
||||
trapFile.foreach_stmt_desugar(this, m, ForeachSymbolType.GetEnumeratorMethod);
|
||||
}
|
||||
|
||||
if (info.MoveNextMethod != null)
|
||||
{
|
||||
var m = Method.Create(cx, info.MoveNextMethod);
|
||||
trapFile.foreach_stmt_desugar(this, m, ForeachSymbolType.MoveNextMethod);
|
||||
}
|
||||
|
||||
if (info.DisposeMethod != null)
|
||||
{
|
||||
var m = Method.Create(cx, info.DisposeMethod);
|
||||
trapFile.foreach_stmt_desugar(this, m, ForeachSymbolType.DisposeMethod);
|
||||
}
|
||||
|
||||
if (info.CurrentProperty != null)
|
||||
{
|
||||
var p = Property.Create(cx, info.CurrentProperty);
|
||||
trapFile.foreach_stmt_desugar(this, p, ForeachSymbolType.CurrentProperty);
|
||||
}
|
||||
|
||||
if (info.ElementType != null)
|
||||
{
|
||||
var t = Type.Create(cx, info.ElementType);
|
||||
trapFile.foreach_stmt_desugar(this, t, ForeachSymbolType.ElementType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,10 +53,15 @@ namespace Semmle.Extraction.CSharp
|
||||
trapFile.WriteTuple("catch_type", @catch, type, explicityCaught ? 1 : 2);
|
||||
}
|
||||
|
||||
internal static void foreach_stmt_info(this TextWriter trapFile, Entities.Statements.ForEach @foreach, Type element, Method getEnumerator,
|
||||
Method moveNext, Method dispose, Property current, bool isAsync)
|
||||
internal static void foreach_stmt_info(this TextWriter trapFile, Entities.Statements.ForEach @foreach, bool isAsync)
|
||||
{
|
||||
trapFile.WriteTuple("foreach_stmt_info", @foreach, element, getEnumerator, moveNext, dispose, current, isAsync ? 2 : 1);
|
||||
trapFile.WriteTuple("foreach_stmt_info", @foreach, isAsync ? 2 : 1);
|
||||
}
|
||||
|
||||
internal static void foreach_stmt_desugar(this TextWriter trapFile, Entities.Statements.ForEach @foreach, IEntity entity,
|
||||
Entities.Statements.ForEach.ForeachSymbolType type)
|
||||
{
|
||||
trapFile.WriteTuple("foreach_stmt_desugar", @foreach, entity, (int)type);
|
||||
}
|
||||
|
||||
internal static void commentblock(this TextWriter trapFile, CommentBlock k)
|
||||
|
||||
@@ -44,7 +44,7 @@ predicate potentiallyAccessedByForEach(Method m) {
|
||||
m.hasName("GetEnumerator") and
|
||||
m.getDeclaringType().getABaseType+().hasQualifiedName("System.Collections.IEnumerable")
|
||||
or
|
||||
foreach_stmt_info(_, _, m, _, _, _, _)
|
||||
foreach_stmt_desugar(_, m, 1)
|
||||
}
|
||||
|
||||
predicate isRecursivelyLiveExpression(Expr e) {
|
||||
|
||||
@@ -583,25 +583,25 @@ class ForeachStmt extends LoopStmt, @foreach_stmt {
|
||||
Expr getIterableExpr() { result = this.getChild(1) }
|
||||
|
||||
/** Gets the called `GetEnumerator` method. */
|
||||
Method getGetEnumerator() { foreach_stmt_info(this, _, result, _, _, _, _) }
|
||||
Method getGetEnumerator() { foreach_stmt_desugar(this, result, 1) }
|
||||
|
||||
/** Gets the called `MoveNext` or `MoveNextAsync` method. */
|
||||
Method getMoveNext() { foreach_stmt_info(this, _, _, result, _, _, _) }
|
||||
Method getMoveNext() { foreach_stmt_desugar(this, result, 3) }
|
||||
|
||||
/** Gets the called `Dispose` or `DisposeAsync` method. */
|
||||
Method getDispose() { foreach_stmt_info(this, _, _, _, result, _, _) }
|
||||
Method getDispose() { foreach_stmt_desugar(this, result, 4) }
|
||||
|
||||
/** Gets the called `Current` property. */
|
||||
Property getCurrent() { foreach_stmt_info(this, _, _, _, _, result, _) }
|
||||
Property getCurrent() { foreach_stmt_desugar(this, result, 2) }
|
||||
|
||||
/**
|
||||
* Gets the intermediate type to which the `Current` property is converted before
|
||||
* being converted to the iteration variable type.
|
||||
*/
|
||||
Type getElementType() { foreach_stmt_info(this, result, _, _, _, _, _) }
|
||||
Type getElementType() { foreach_stmt_desugar(this, result, 5) }
|
||||
|
||||
/** Holds if this `foreach` statement is asynchronous. */
|
||||
predicate isAsync() { foreach_stmt_info(this, _, _, _, _, _, 2) }
|
||||
predicate isAsync() { foreach_stmt_info(this, 2) }
|
||||
|
||||
override string toString() { result = "foreach (... ... in ...) ..." }
|
||||
|
||||
|
||||
@@ -984,13 +984,16 @@ catch_type(
|
||||
|
||||
foreach_stmt_info(
|
||||
unique int id: @foreach_stmt ref,
|
||||
int element_type_id: @type_or_ref ref,
|
||||
int getenumerator_id: @method ref,
|
||||
int movenext_id: @method ref,
|
||||
int dispose_id: @method ref,
|
||||
int current_id: @property ref,
|
||||
int kind: int ref /* non-async = 1, async = 2 */);
|
||||
|
||||
@foreach_symbol = @method | @property | @type_or_ref;
|
||||
|
||||
#keyset[id, kind]
|
||||
foreach_stmt_desugar(
|
||||
int id: @foreach_stmt ref,
|
||||
int symbol: @foreach_symbol ref,
|
||||
int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
|
||||
|
||||
/** EXPRESSIONS **/
|
||||
|
||||
expressions(
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
description: Add 'foreach_stmt_info' relation.
|
||||
description: Add 'foreach_stmt_info' and 'foreach_stmt_desugar' relations.
|
||||
compatibility: backwards
|
||||
Reference in New Issue
Block a user