C#: Fix global statement extraction by extracting statements inside the implicit main method context

This commit is contained in:
Tamas Vajk 2022-06-20 09:31:44 +02:00
Родитель c460e5757b
Коммит 51f0a928dc
6 изменённых файлов: 56 добавлений и 18 удалений

Просмотреть файл

@ -0,0 +1,36 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities.Statements;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
internal class ImplicitMainMethod : OrdinaryMethod
{
private readonly List<GlobalStatementSyntax> globalStatements;
public ImplicitMainMethod(Context cx, IMethodSymbol symbol, List<GlobalStatementSyntax> globalStatements)
: base(cx, symbol)
{
this.globalStatements = globalStatements;
}
protected override void PopulateMethodBody(TextWriter trapFile)
{
GlobalStatementsBlock.Create(Context, this, globalStatements);
}
public static ImplicitMainMethod Create(Context cx, IMethodSymbol method, List<GlobalStatementSyntax> globalStatements)
{
return ImplicitMainMethodFactory.Instance.CreateEntity(cx, method, (method, globalStatements));
}
private class ImplicitMainMethodFactory : CachedEntityFactory<(IMethodSymbol, List<GlobalStatementSyntax>), ImplicitMainMethod>
{
public static ImplicitMainMethodFactory Instance { get; } = new ImplicitMainMethodFactory();
public override ImplicitMainMethod Create(Context cx, (IMethodSymbol, List<GlobalStatementSyntax>) init) => new ImplicitMainMethod(cx, init.Item1, init.Item2);
}
}
}

Просмотреть файл

@ -46,7 +46,7 @@ namespace Semmle.Extraction.CSharp.Entities
// so there's nothing to extract.
}
private void PopulateMethodBody(TextWriter trapFile)
protected virtual void PopulateMethodBody(TextWriter trapFile)
{
if (!IsSourceDeclaration)
return;

Просмотреть файл

@ -8,7 +8,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
internal class OrdinaryMethod : Method
{
private OrdinaryMethod(Context cx, IMethodSymbol init)
protected OrdinaryMethod(Context cx, IMethodSymbol init)
: base(cx, init) { }
public override string Name => Symbol.GetName();

Просмотреть файл

@ -2,17 +2,22 @@ using Semmle.Extraction.Kinds;
using System.Linq;
using System.IO;
using Semmle.Extraction.Entities;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
internal class GlobalStatementsBlock : Statement
{
private readonly Method parent;
private readonly List<GlobalStatementSyntax> globalStatements;
private GlobalStatementsBlock(Context cx, Method parent)
private GlobalStatementsBlock(Context cx, Method parent, List<GlobalStatementSyntax> globalStatements)
: base(cx, StmtKind.BLOCK, parent, 0)
{
this.parent = parent;
this.globalStatements = globalStatements;
}
public override Microsoft.CodeAnalysis.Location? ReportingLocation
@ -27,9 +32,9 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
}
}
public static GlobalStatementsBlock Create(Context cx, Method parent)
public static GlobalStatementsBlock Create(Context cx, Method parent, List<GlobalStatementSyntax> globalStatements)
{
var ret = new GlobalStatementsBlock(cx, parent);
var ret = new GlobalStatementsBlock(cx, parent, globalStatements);
ret.TryPopulate();
return ret;
}
@ -37,6 +42,14 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
protected override void PopulateStatement(TextWriter trapFile)
{
trapFile.stmt_location(this, Context.CreateLocation(ReportingLocation));
for (var i = 0; i < globalStatements.Count; i++)
{
if (globalStatements[i].Statement is not null)
{
Statement.Create(Context, globalStatements[i].Statement, this, i);
}
}
}
}
}

Просмотреть файл

@ -3,7 +3,6 @@ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Util.Logging;
using Semmle.Extraction.CSharp.Entities;
using Semmle.Extraction.CSharp.Entities.Statements;
using System.Linq;
namespace Semmle.Extraction.CSharp.Populators
@ -60,23 +59,14 @@ namespace Semmle.Extraction.CSharp.Populators
}
var entryPoint = Cx.Compilation.GetEntryPoint(System.Threading.CancellationToken.None);
var entryMethod = Method.Create(Cx, entryPoint);
if (entryMethod is null)
if (entryPoint is null)
{
Cx.ExtractionError("No entry method found. Skipping the extraction of global statements.",
null, Cx.CreateLocation(globalStatements[0].GetLocation()), null, Severity.Info);
return;
}
var block = GlobalStatementsBlock.Create(Cx, entryMethod);
for (var i = 0; i < globalStatements.Count; i++)
{
if (globalStatements[i].Statement is not null)
{
Statement.Create(Cx, globalStatements[i].Statement, block, i);
}
}
ImplicitMainMethod.Create(Cx, entryPoint, globalStatements);
}
}
}

Просмотреть файл

@ -1 +0,0 @@
| GlobalStmt.cs:13:6:13:6 | TagStack unexpectedly empty | Unexpected C# extractor error: TagStack unexpectedly empty\n |