1+ using System ;
2+ using System . Collections . Generic ;
13using Microsoft . CodeAnalysis . CSharp . Syntax ;
24using Semmle . Extraction . Kinds ;
35using 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