Rework if/elif/else/endif extraction

This commit is contained in:
Tamas Vajk
2021-01-27 09:24:25 +01:00
parent 72547b89e6
commit 1ab4af275d
8 changed files with 76 additions and 77 deletions

View File

@@ -5,16 +5,22 @@ namespace Semmle.Extraction.CSharp.Entities
{
internal class ElifDirective : PreprocessorDirective<ElifDirectiveTriviaSyntax>, IIfSiblingDirective, IExpressionParentEntity
{
public ElifDirective(Context cx, ElifDirectiveTriviaSyntax trivia)
: base(cx, trivia)
private readonly IfDirective start;
private readonly int index;
public ElifDirective(Context cx, ElifDirectiveTriviaSyntax trivia, IfDirective start, int index)
: base(cx, trivia, populateFromBase: false)
{
this.start = start;
this.index = index;
TryPopulate();
}
public bool IsTopLevelParent => true;
protected override void PopulatePreprocessor(TextWriter trapFile)
{
trapFile.directive_elifs(this, trivia.BranchTaken, trivia.ConditionValue);
trapFile.directive_elifs(this, trivia.BranchTaken, trivia.ConditionValue, start, index);
Expression.Create(cx, trivia.Condition, this, 0);
}

View File

@@ -5,14 +5,20 @@ namespace Semmle.Extraction.CSharp.Entities
{
internal class ElseDirective : PreprocessorDirective<ElseDirectiveTriviaSyntax>, IIfSiblingDirective
{
public ElseDirective(Context cx, ElseDirectiveTriviaSyntax trivia)
: base(cx, trivia)
private readonly IfDirective start;
private readonly int index;
public ElseDirective(Context cx, ElseDirectiveTriviaSyntax trivia, IfDirective start, int index)
: base(cx, trivia, populateFromBase: false)
{
this.start = start;
this.index = index;
TryPopulate();
}
protected override void PopulatePreprocessor(TextWriter trapFile)
{
trapFile.directive_elses(this, trivia.BranchTaken);
trapFile.directive_elses(this, trivia.BranchTaken, start, index);
}
}
}

View File

@@ -5,14 +5,18 @@ namespace Semmle.Extraction.CSharp.Entities
{
internal class EndIfDirective : PreprocessorDirective<EndIfDirectiveTriviaSyntax>
{
public EndIfDirective(Context cx, EndIfDirectiveTriviaSyntax trivia)
: base(cx, trivia)
private readonly IfDirective start;
public EndIfDirective(Context cx, EndIfDirectiveTriviaSyntax trivia, IfDirective start)
: base(cx, trivia, populateFromBase: false)
{
this.start = start;
TryPopulate();
}
protected override void PopulatePreprocessor(TextWriter trapFile)
{
trapFile.directive_endifs(this);
trapFile.directive_endifs(this, start);
}
}
}

View File

@@ -1,13 +1,10 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
internal class IfDirective : PreprocessorDirective<IfDirectiveTriviaSyntax>, IExpressionParentEntity
{
private readonly List<IIfSiblingDirective> branches = new List<IIfSiblingDirective>();
public IfDirective(Context cx, IfDirectiveTriviaSyntax trivia)
: base(cx, trivia)
{
@@ -21,20 +18,5 @@ namespace Semmle.Extraction.CSharp.Entities
Expression.Create(cx, trivia.Condition, this, 0);
}
internal void Add(IIfSiblingDirective branch)
{
branches.Add(branch);
}
internal void WriteBranches(EndIfDirective endif)
{
cx.TrapWriter.Writer.directive_if_endif(this, endif);
var siblings = 0;
foreach (var branch in branches)
{
cx.TrapWriter.Writer.directive_if_siblings(this, branch, siblings++);
}
}
}
}

View File

@@ -76,51 +76,63 @@ namespace Semmle.Extraction.CSharp.Populators
new Entities.EndRegionDirective(cx, node, start);
}
private readonly Stack<Entities.IfDirective> ifStarts = new Stack<Entities.IfDirective>();
private class IfDirectiveStackElement
{
public Entities.IfDirective Entity { get; }
public int SiblingCount { get; set; }
public IfDirectiveStackElement(Entities.IfDirective entity)
{
Entity = entity;
}
}
private readonly Stack<IfDirectiveStackElement> ifStarts = new Stack<IfDirectiveStackElement>();
public override void VisitIfDirectiveTrivia(IfDirectiveTriviaSyntax node)
{
var ifStart = new Entities.IfDirective(cx, node);
ifStarts.Push(ifStart);
ifStarts.Push(new IfDirectiveStackElement(ifStart));
}
public override void VisitEndIfDirectiveTrivia(EndIfDirectiveTriviaSyntax node)
{
var endif = new Entities.EndIfDirective(cx, node);
if (ifStarts.Count == 0)
{
cx.ExtractionError("Couldn't find start if", null,
Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning);
return;
}
var start = ifStarts.Pop();
start.WriteBranches(endif);
new Entities.EndIfDirective(cx, node, start.Entity);
}
public override void VisitElifDirectiveTrivia(ElifDirectiveTriviaSyntax node)
{
var elif = new Entities.ElifDirective(cx, node);
if (ifStarts.Count == 0)
{
cx.ExtractionError("Couldn't find start if", null,
Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning);
return;
}
var start = ifStarts.Peek();
start.Add(elif);
new Entities.ElifDirective(cx, node, start.Entity, start.SiblingCount++);
}
public override void VisitElseDirectiveTrivia(ElseDirectiveTriviaSyntax node)
{
var elseDirective = new Entities.ElseDirective(cx, node);
if (ifStarts.Count == 0)
{
cx.ExtractionError("Couldn't find start if", null,
Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning);
return;
}
var start = ifStarts.Peek();
start.Add(elseDirective);
new Entities.ElseDirective(cx, node, start.Entity, start.SiblingCount++);
}
}
}

View File

@@ -684,29 +684,21 @@ namespace Semmle.Extraction.CSharp
trapFile.WriteTuple("directive_ifs", directive, branchTaken ? 1 : 0, conditionValue ? 1 : 0);
}
internal static void directive_elifs(this TextWriter trapFile, ElifDirective directive, bool branchTaken, bool conditionValue)
internal static void directive_elifs(this TextWriter trapFile, ElifDirective directive, bool branchTaken, bool conditionValue,
IfDirective start, int index)
{
trapFile.WriteTuple("directive_elifs", directive, branchTaken ? 1 : 0, conditionValue ? 1 : 0);
trapFile.WriteTuple("directive_elifs", directive, branchTaken ? 1 : 0, conditionValue ? 1 : 0, start, index);
}
internal static void directive_elses(this TextWriter trapFile, ElseDirective directive, bool branchTaken)
internal static void directive_elses(this TextWriter trapFile, ElseDirective directive, bool branchTaken,
IfDirective start, int index)
{
trapFile.WriteTuple("directive_elses", directive, branchTaken ? 1 : 0);
trapFile.WriteTuple("directive_elses", directive, branchTaken ? 1 : 0, start, index);
}
internal static void directive_endifs(this TextWriter trapFile, EndIfDirective directive)
internal static void directive_endifs(this TextWriter trapFile, EndIfDirective directive, IfDirective start)
{
trapFile.WriteTuple("directive_endifs", directive);
}
internal static void directive_if_endif(this TextWriter trapFile, IfDirective start, EndIfDirective end)
{
trapFile.WriteTuple("directive_if_endif", start, end);
}
internal static void directive_if_siblings(this TextWriter trapFile, IfDirective start, IIfSiblingDirective siblingDirective, int index)
{
trapFile.WriteTuple("directive_if_siblings", start, siblingDirective, index);
trapFile.WriteTuple("directive_endifs", directive, start);
}
internal static void directive_define_symbols(this TextWriter trapFile, DefineSymbol symb, string name)