Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1ab4af2

Browse files
committed
Rework if/elif/else/endif extraction
1 parent 72547b8 commit 1ab4af2

8 files changed

Lines changed: 75 additions & 76 deletions

File tree

csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/ElifDirective.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,22 @@ namespace Semmle.Extraction.CSharp.Entities
55
{
66
internal class ElifDirective : PreprocessorDirective<ElifDirectiveTriviaSyntax>, IIfSiblingDirective, IExpressionParentEntity
77
{
8-
public ElifDirective(Context cx, ElifDirectiveTriviaSyntax trivia)
9-
: base(cx, trivia)
8+
private readonly IfDirective start;
9+
private readonly int index;
10+
11+
public ElifDirective(Context cx, ElifDirectiveTriviaSyntax trivia, IfDirective start, int index)
12+
: base(cx, trivia, populateFromBase: false)
1013
{
14+
this.start = start;
15+
this.index = index;
16+
TryPopulate();
1117
}
1218

1319
public bool IsTopLevelParent => true;
1420

1521
protected override void PopulatePreprocessor(TextWriter trapFile)
1622
{
17-
trapFile.directive_elifs(this, trivia.BranchTaken, trivia.ConditionValue);
23+
trapFile.directive_elifs(this, trivia.BranchTaken, trivia.ConditionValue, start, index);
1824

1925
Expression.Create(cx, trivia.Condition, this, 0);
2026
}

csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/ElseDirective.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@ namespace Semmle.Extraction.CSharp.Entities
55
{
66
internal class ElseDirective : PreprocessorDirective<ElseDirectiveTriviaSyntax>, IIfSiblingDirective
77
{
8-
public ElseDirective(Context cx, ElseDirectiveTriviaSyntax trivia)
9-
: base(cx, trivia)
8+
private readonly IfDirective start;
9+
private readonly int index;
10+
11+
public ElseDirective(Context cx, ElseDirectiveTriviaSyntax trivia, IfDirective start, int index)
12+
: base(cx, trivia, populateFromBase: false)
1013
{
14+
this.start = start;
15+
this.index = index;
16+
TryPopulate();
1117
}
1218

1319
protected override void PopulatePreprocessor(TextWriter trapFile)
1420
{
15-
trapFile.directive_elses(this, trivia.BranchTaken);
21+
trapFile.directive_elses(this, trivia.BranchTaken, start, index);
1622
}
1723
}
1824
}

csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/EndIfDirective.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@ namespace Semmle.Extraction.CSharp.Entities
55
{
66
internal class EndIfDirective : PreprocessorDirective<EndIfDirectiveTriviaSyntax>
77
{
8-
public EndIfDirective(Context cx, EndIfDirectiveTriviaSyntax trivia)
9-
: base(cx, trivia)
8+
private readonly IfDirective start;
9+
10+
public EndIfDirective(Context cx, EndIfDirectiveTriviaSyntax trivia, IfDirective start)
11+
: base(cx, trivia, populateFromBase: false)
1012
{
13+
this.start = start;
14+
TryPopulate();
1115
}
1216

1317
protected override void PopulatePreprocessor(TextWriter trapFile)
1418
{
15-
trapFile.directive_endifs(this);
19+
trapFile.directive_endifs(this, start);
1620
}
1721
}
1822
}
Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
using Microsoft.CodeAnalysis.CSharp.Syntax;
2-
using System.Collections.Generic;
32
using System.IO;
43

54
namespace Semmle.Extraction.CSharp.Entities
65
{
76
internal class IfDirective : PreprocessorDirective<IfDirectiveTriviaSyntax>, IExpressionParentEntity
87
{
9-
private readonly List<IIfSiblingDirective> branches = new List<IIfSiblingDirective>();
10-
118
public IfDirective(Context cx, IfDirectiveTriviaSyntax trivia)
129
: base(cx, trivia)
1310
{
@@ -21,20 +18,5 @@ protected override void PopulatePreprocessor(TextWriter trapFile)
2118

2219
Expression.Create(cx, trivia.Condition, this, 0);
2320
}
24-
25-
internal void Add(IIfSiblingDirective branch)
26-
{
27-
branches.Add(branch);
28-
}
29-
30-
internal void WriteBranches(EndIfDirective endif)
31-
{
32-
cx.TrapWriter.Writer.directive_if_endif(this, endif);
33-
var siblings = 0;
34-
foreach (var branch in branches)
35-
{
36-
cx.TrapWriter.Writer.directive_if_siblings(this, branch, siblings++);
37-
}
38-
}
3921
}
4022
}

csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,51 +76,63 @@ public override void VisitEndRegionDirectiveTrivia(EndRegionDirectiveTriviaSynta
7676
new Entities.EndRegionDirective(cx, node, start);
7777
}
7878

79-
private readonly Stack<Entities.IfDirective> ifStarts = new Stack<Entities.IfDirective>();
79+
private class IfDirectiveStackElement
80+
{
81+
public Entities.IfDirective Entity { get; }
82+
public int SiblingCount { get; set; }
83+
84+
85+
public IfDirectiveStackElement(Entities.IfDirective entity)
86+
{
87+
Entity = entity;
88+
}
89+
}
90+
91+
private readonly Stack<IfDirectiveStackElement> ifStarts = new Stack<IfDirectiveStackElement>();
8092

8193
public override void VisitIfDirectiveTrivia(IfDirectiveTriviaSyntax node)
8294
{
8395
var ifStart = new Entities.IfDirective(cx, node);
84-
ifStarts.Push(ifStart);
96+
ifStarts.Push(new IfDirectiveStackElement(ifStart));
8597
}
8698

8799
public override void VisitEndIfDirectiveTrivia(EndIfDirectiveTriviaSyntax node)
88100
{
89-
var endif = new Entities.EndIfDirective(cx, node);
90101
if (ifStarts.Count == 0)
91102
{
92103
cx.ExtractionError("Couldn't find start if", null,
93104
Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning);
94105
return;
95106
}
107+
96108
var start = ifStarts.Pop();
97-
start.WriteBranches(endif);
109+
new Entities.EndIfDirective(cx, node, start.Entity);
98110
}
99111

100112
public override void VisitElifDirectiveTrivia(ElifDirectiveTriviaSyntax node)
101113
{
102-
var elif = new Entities.ElifDirective(cx, node);
103114
if (ifStarts.Count == 0)
104115
{
105116
cx.ExtractionError("Couldn't find start if", null,
106117
Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning);
107118
return;
108119
}
120+
109121
var start = ifStarts.Peek();
110-
start.Add(elif);
122+
new Entities.ElifDirective(cx, node, start.Entity, start.SiblingCount++);
111123
}
112124

113125
public override void VisitElseDirectiveTrivia(ElseDirectiveTriviaSyntax node)
114126
{
115-
var elseDirective = new Entities.ElseDirective(cx, node);
116127
if (ifStarts.Count == 0)
117128
{
118129
cx.ExtractionError("Couldn't find start if", null,
119130
Extraction.Entities.Location.Create(cx, node.GetLocation()), null, Util.Logging.Severity.Warning);
120131
return;
121132
}
133+
122134
var start = ifStarts.Peek();
123-
start.Add(elseDirective);
135+
new Entities.ElseDirective(cx, node, start.Entity, start.SiblingCount++);
124136
}
125137
}
126138
}

csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -684,29 +684,21 @@ internal static void directive_ifs(this TextWriter trapFile, IfDirective directi
684684
trapFile.WriteTuple("directive_ifs", directive, branchTaken ? 1 : 0, conditionValue ? 1 : 0);
685685
}
686686

687-
internal static void directive_elifs(this TextWriter trapFile, ElifDirective directive, bool branchTaken, bool conditionValue)
687+
internal static void directive_elifs(this TextWriter trapFile, ElifDirective directive, bool branchTaken, bool conditionValue,
688+
IfDirective start, int index)
688689
{
689-
trapFile.WriteTuple("directive_elifs", directive, branchTaken ? 1 : 0, conditionValue ? 1 : 0);
690+
trapFile.WriteTuple("directive_elifs", directive, branchTaken ? 1 : 0, conditionValue ? 1 : 0, start, index);
690691
}
691692

692-
internal static void directive_elses(this TextWriter trapFile, ElseDirective directive, bool branchTaken)
693+
internal static void directive_elses(this TextWriter trapFile, ElseDirective directive, bool branchTaken,
694+
IfDirective start, int index)
693695
{
694-
trapFile.WriteTuple("directive_elses", directive, branchTaken ? 1 : 0);
696+
trapFile.WriteTuple("directive_elses", directive, branchTaken ? 1 : 0, start, index);
695697
}
696698

697-
internal static void directive_endifs(this TextWriter trapFile, EndIfDirective directive)
699+
internal static void directive_endifs(this TextWriter trapFile, EndIfDirective directive, IfDirective start)
698700
{
699-
trapFile.WriteTuple("directive_endifs", directive);
700-
}
701-
702-
internal static void directive_if_endif(this TextWriter trapFile, IfDirective start, EndIfDirective end)
703-
{
704-
trapFile.WriteTuple("directive_if_endif", start, end);
705-
}
706-
707-
internal static void directive_if_siblings(this TextWriter trapFile, IfDirective start, IIfSiblingDirective siblingDirective, int index)
708-
{
709-
trapFile.WriteTuple("directive_if_siblings", start, siblingDirective, index);
701+
trapFile.WriteTuple("directive_endifs", directive, start);
710702
}
711703

712704
internal static void directive_define_symbols(this TextWriter trapFile, DefineSymbol symb, string name)

csharp/ql/src/semmle/code/csharp/Preprocessor.qll

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,13 @@ class IfDirective extends ConditionalDirective, @directive_if {
281281
override predicate conditionMatched() { directive_ifs(this, _, 1) }
282282

283283
/** Gets the closing `#endif` preprocessor directive. */
284-
EndifDirective getEndifDirective() { directive_if_endif(this, result) }
284+
EndifDirective getEndifDirective() { directive_endifs(result, this) }
285285

286286
/** Gets the sibling `#elif` or `#else` preprocessor directive at index `sibling`. */
287-
BranchDirective getSiblingDirective(int sibling) { directive_if_siblings(this, result, sibling) }
287+
BranchDirective getSiblingDirective(int sibling) {
288+
directive_elifs(result, _, _, this, sibling) or
289+
directive_elses(result, _, this, sibling)
290+
}
288291

289292
/** Gets a sibling `#elif` or `#else` preprocessor directive. */
290293
BranchDirective getASiblingDirective() { result = getSiblingDirective(_) }
@@ -298,17 +301,18 @@ class IfDirective extends ConditionalDirective, @directive_if {
298301
* An `#elif` preprocessor directive.
299302
*/
300303
class ElifDirective extends ConditionalDirective, @directive_elif {
301-
override predicate branchTaken() { directive_elifs(this, 1, _) }
304+
override predicate branchTaken() { directive_elifs(this, 1, _, _, _) }
302305

303-
override predicate conditionMatched() { directive_elifs(this, _, 1) }
306+
override predicate conditionMatched() { directive_elifs(this, _, 1, _, _) }
304307

305308
/** Gets the opening `#if` preprocessor directive. */
306-
IfDirective getIfDirective() { directive_if_siblings(result, this, _) }
309+
IfDirective getIfDirective() { directive_elifs(this, _, _, result, _) }
307310

308311
/** Gets the successive branching preprocessor directive (`#elif` or `#else`), if any. */
309312
BranchDirective getSuccSiblingDirective() {
310313
exists(IfDirective i, int index |
311-
directive_if_siblings(i, this, index) and directive_if_siblings(i, result, index + 1)
314+
this = i.getSiblingDirective(index) and
315+
result = i.getSiblingDirective(index + 1)
312316
)
313317
}
314318

@@ -322,9 +326,9 @@ class ElifDirective extends ConditionalDirective, @directive_elif {
322326
*/
323327
class ElseDirective extends BranchDirective, @directive_else {
324328
/** Gets the opening `#if` preprocessor directive. */
325-
IfDirective getIfDirective() { directive_if_siblings(result, this, _) }
329+
IfDirective getIfDirective() { directive_elses(this, _, result, _) }
326330

327-
override predicate branchTaken() { directive_elses(this, 1) }
331+
override predicate branchTaken() { directive_elses(this, 1, _, _) }
328332

329333
override string toString() { result = "#else" }
330334

@@ -336,7 +340,7 @@ class ElseDirective extends BranchDirective, @directive_else {
336340
*/
337341
class EndifDirective extends PreprocessorDirective, @directive_endif {
338342
/** Gets the opening `#if` preprocessor directive. */
339-
IfDirective getIfDirective() { directive_if_endif(result, this) }
343+
IfDirective getIfDirective() { directive_endifs(this, result) }
340344

341345
override string toString() { result = "#endif" }
342346

csharp/ql/src/semmlecode.csharp.dbscheme

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -346,27 +346,20 @@ directive_ifs(
346346
directive_elifs(
347347
unique int id: @directive_elif,
348348
int branchTaken: int ref, /* 0: false, 1: true */
349-
int conditionValue: int ref); /* 0: false, 1: true */
349+
int conditionValue: int ref, /* 0: false, 1: true */
350+
int parent: @directive_if ref,
351+
int index: int ref);
350352

351353
directive_elses(
352354
unique int id: @directive_else,
353-
int branchTaken: int ref); /* 0: false, 1: true */
355+
int branchTaken: int ref, /* 0: false, 1: true */
356+
int parent: @directive_if ref,
357+
int index: int ref);
354358

359+
#keyset[id, start]
355360
directive_endifs(
356-
unique int id: @directive_endif);
357-
358-
#keyset[start, end]
359-
directive_if_endif(
360-
unique int start: @directive_if ref,
361-
unique int end: @directive_endif ref);
362-
363-
@directive_if_sibling = @directive_else | @directive_elif;
364-
365-
#keyset[start, index]
366-
directive_if_siblings(
367-
int start: @directive_if ref,
368-
int sibling: @directive_if_sibling ref,
369-
int index: int ref);
361+
unique int id: @directive_endif,
362+
unique int start: @directive_if ref);
370363

371364
directive_define_symbols(
372365
unique int id: @define_symbol_expr ref,

0 commit comments

Comments
 (0)