Skip to content

Commit 83e7fae

Browse files
committed
C#: Desugar property patterns that uses member access syntax.
1 parent 26d9848 commit 83e7fae

File tree

1 file changed

+81
-5
lines changed

1 file changed

+81
-5
lines changed
Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System;
2+
using System.Collections.Generic;
13
using Microsoft.CodeAnalysis.CSharp.Syntax;
24
using Semmle.Extraction.Kinds;
35
using Semmle.Extraction.Entities;
@@ -10,17 +12,91 @@ internal PropertyPattern(Context cx, PropertyPatternClauseSyntax pp, IExpression
1012
base(new ExpressionInfo(cx, null, cx.CreateLocation(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null))
1113
{
1214
child = 0;
13-
var trapFile = cx.TrapWriter.Writer;
1415
foreach (var sub in pp.Subpatterns)
1516
{
16-
var p = Expressions.Pattern.Create(cx, sub.Pattern, this, child++);
17-
if (sub.NameColon is null)
17+
if (sub.ExpressionColon is null)
1818
{
19-
Context.ModelError(sub, "Expected to find 'Name:' in pattern.");
19+
Context.ModelError(sub, "Expected to find 'Expression:' in pattern.");
2020
continue;
2121
}
22-
trapFile.exprorstmt_name(p, sub.NameColon.Name.ToString());
22+
MakeExpressions(cx, this, sub, child++);
23+
}
24+
}
25+
26+
private class AccessStep
27+
{
28+
public readonly string Identifier;
29+
public readonly Microsoft.CodeAnalysis.Location Location;
30+
31+
public AccessStep(string identifier, Microsoft.CodeAnalysis.Location location)
32+
{
33+
Identifier = identifier;
34+
Location = location;
35+
}
36+
}
37+
38+
private class AccessStepPack
39+
{
40+
public readonly List<AccessStep> Prefix = new List<AccessStep>();
41+
public AccessStep Last { get; private set; }
42+
43+
public AccessStepPack Add(string identifier, Microsoft.CodeAnalysis.Location location)
44+
{
45+
Prefix.Add(Last);
46+
Last = new AccessStep(identifier, location);
47+
return this;
48+
}
49+
50+
public AccessStepPack(string identifier, Microsoft.CodeAnalysis.Location location)
51+
{
52+
Last = new AccessStep(identifier, location);
53+
}
54+
}
55+
56+
private static AccessStepPack GetAccessStepPack(ExpressionSyntax syntax)
57+
{
58+
switch (syntax)
59+
{
60+
case MemberAccessExpressionSyntax memberAccess:
61+
return GetAccessStepPack(memberAccess.Expression).Add(memberAccess.Name.Identifier.ValueText, memberAccess.Name.Identifier.GetLocation());
62+
case IdentifierNameSyntax identifier:
63+
return new AccessStepPack(identifier.Identifier.Text, identifier.GetLocation());
64+
default:
65+
throw new InternalError(syntax, "Unexpected expression syntax in property patterns.");
2366
}
2467
}
68+
69+
private static AccessStepPack GetAccessStepPack(BaseExpressionColonSyntax syntax)
70+
{
71+
switch (syntax)
72+
{
73+
case NameColonSyntax ncs:
74+
return new AccessStepPack(ncs.Name.ToString(), ncs.Name.GetLocation());
75+
case ExpressionColonSyntax ecs:
76+
return GetAccessStepPack(ecs.Expression);
77+
default:
78+
throw new InternalError(syntax, "Unsupported expression colon in property pattern.");
79+
};
80+
}
81+
82+
private static Expression CreateSyntheticExp(Context cx, Microsoft.CodeAnalysis.Location location, IExpressionParentEntity parent, int child) =>
83+
new Expression(new ExpressionInfo(cx, null, cx.CreateLocation(location), ExprKind.PROPERTY_PATTERN, parent, child, false, null));
84+
85+
private static void MakeExpressions(Context cx, IExpressionParentEntity parent, SubpatternSyntax syntax, int child)
86+
{
87+
var trapFile = cx.TrapWriter.Writer;
88+
var pack = GetAccessStepPack(syntax.ExpressionColon!);
89+
90+
foreach (var step in pack.Prefix)
91+
{
92+
var exp = CreateSyntheticExp(cx, step.Location, parent, child);
93+
trapFile.exprorstmt_name(exp, step.Identifier);
94+
parent = exp;
95+
child = 0;
96+
}
97+
98+
var p = Expressions.Pattern.Create(cx, syntax.Pattern, parent, child);
99+
trapFile.exprorstmt_name(p, pack.Last.Identifier);
100+
}
25101
}
26102
}

0 commit comments

Comments
 (0)