@@ -23,12 +23,6 @@ private abstract class BaseContext(
23
23
public FragmentDefinitionNode GetFragmentDefinition ( string name )
24
24
=> fragmentLookup [ name ] ;
25
25
26
- public void AddSelection ( ISelectionNode selection )
27
- {
28
- Selections ??= new HashSet < ISelectionNode > ( SyntaxNodeComparer . Instance ) ;
29
- Selections . Add ( selection ) ;
30
- }
31
-
32
26
public virtual BaseContext GetOrCreateFragmentContext (
33
27
InlineFragmentNode inlineFragmentNode ,
34
28
ITypeDefinition typeCondition )
@@ -46,7 +40,7 @@ public virtual BaseContext GetOrCreateFragmentContext(
46
40
return fragmentContext ;
47
41
}
48
42
49
- public virtual BaseContext ? AddField ( FieldNode fieldNode , ITypeDefinition fieldType )
43
+ public virtual BaseContext ? GetOrCreateFieldContext ( FieldNode fieldNode , ITypeDefinition fieldType )
50
44
{
51
45
if ( fieldNode . SelectionSet is not null )
52
46
{
@@ -89,13 +83,63 @@ public ConditionalContext GetOrCreateConditionalContext(Conditional conditional)
89
83
90
84
return conditionalContext ;
91
85
}
86
+
87
+ protected void AddSelection ( ISelectionNode selection )
88
+ {
89
+ Selections ??= new HashSet < ISelectionNode > ( SyntaxNodeComparer . Instance ) ;
90
+ Selections . Add ( selection ) ;
91
+ }
92
+
93
+ protected internal void RemoveSelection ( ISelectionNode selection )
94
+ {
95
+ Selections ? . Remove ( selection ) ;
96
+
97
+ if ( selection is FieldNode fieldNode )
98
+ {
99
+ FieldContexts ? . Remove ( fieldNode ) ;
100
+ }
101
+ else if ( selection is InlineFragmentNode inlineFragmentNode )
102
+ {
103
+ FragmentContexts ? . Remove ( inlineFragmentNode ) ;
104
+ }
105
+ }
92
106
}
93
107
94
108
private sealed class Context (
95
109
ITypeDefinition type ,
96
110
Dictionary < string , FragmentDefinitionNode > fragmentLookup )
97
111
: BaseContext ( type , fragmentLookup )
98
112
{
113
+ public Dictionary < ISelectionNode , List < ConditionalContext > > ? ConditionalParentContexts { get ; set ; }
114
+
115
+ public override BaseContext ? GetOrCreateFieldContext ( FieldNode fieldNode , ITypeDefinition fieldType )
116
+ {
117
+ var fieldContext = base . GetOrCreateFieldContext ( fieldNode , fieldType ) ;
118
+
119
+ if ( ConditionalParentContexts is not null
120
+ && ConditionalParentContexts . TryGetValue ( fieldNode , out var conditionalContexts ) )
121
+ {
122
+ foreach ( var conditionalContext in conditionalContexts )
123
+ {
124
+ if ( conditionalContext . FieldContexts is not null
125
+ && conditionalContext . FieldContexts . TryGetValue ( fieldNode , out var conditionalFieldContext ) )
126
+ {
127
+ // TODO: This should actually recreate the entire conditional hierarchy up until the first non-conditional parent
128
+ var conditionalContextBelowUnconditionalField =
129
+ GetOrCreateConditionalContext ( conditionalContext . Conditional ) ;
130
+
131
+ // TODO: Merge conditionalFieldContext into conditionalContextBelowUnconditionalField
132
+ }
133
+
134
+ conditionalContext . RemoveSelection ( fieldNode ) ;
135
+ }
136
+
137
+ ConditionalParentContexts . Remove ( fieldNode ) ;
138
+ }
139
+
140
+ return fieldContext ;
141
+ }
142
+
99
143
public override BaseContext GetOrCreateFragmentContext (
100
144
InlineFragmentNode inlineFragmentNode ,
101
145
ITypeDefinition typeCondition )
@@ -115,6 +159,45 @@ private sealed class ConditionalContext(
115
159
{
116
160
public Context UnconditionalContext { get ; } = unconditionalContext ;
117
161
162
+ public Conditional Conditional { get ; } = conditional ;
163
+
164
+ public override BaseContext ? GetOrCreateFieldContext ( FieldNode fieldNode , ITypeDefinition fieldType )
165
+ {
166
+ if ( UnconditionalContext . Selections ? . Contains ( fieldNode ) == true )
167
+ {
168
+ if ( fieldNode . SelectionSet is null )
169
+ {
170
+ return null ;
171
+ }
172
+
173
+ if ( UnconditionalContext . FieldContexts ! . TryGetValue ( fieldNode , out var unconditionalFieldContext ) )
174
+ {
175
+ // TODO: This should actually recreate the entire conditional hierarchy up until the first non-conditional parent
176
+ var conditionalContext = unconditionalFieldContext . GetOrCreateConditionalContext ( Conditional ) ;
177
+
178
+ return conditionalContext ;
179
+ }
180
+ else
181
+ {
182
+ throw new InvalidOperationException (
183
+ "Expected to be able to a find a field context, if the selection exists." ) ;
184
+ }
185
+ }
186
+
187
+ UnconditionalContext . ConditionalParentContexts ??=
188
+ new Dictionary < ISelectionNode , List < ConditionalContext > > ( SyntaxNodeComparer . Instance ) ;
189
+
190
+ if ( ! UnconditionalContext . ConditionalParentContexts . TryGetValue ( fieldNode , out var conditionalContexts ) )
191
+ {
192
+ conditionalContexts = [ ] ;
193
+ UnconditionalContext . ConditionalParentContexts [ fieldNode ] = conditionalContexts ;
194
+ }
195
+
196
+ conditionalContexts . Add ( this ) ;
197
+
198
+ return base . GetOrCreateFieldContext ( fieldNode , fieldType ) ;
199
+ }
200
+
118
201
public override BaseContext GetOrCreateFragmentContext (
119
202
InlineFragmentNode inlineFragmentNode ,
120
203
ITypeDefinition typeCondition )
@@ -123,7 +206,7 @@ public override BaseContext GetOrCreateFragmentContext(
123
206
&& UnconditionalContext . FragmentContexts . TryGetValue ( inlineFragmentNode , out var unconditionalFragmentContext ) )
124
207
{
125
208
// TODO: This should actually recreate the entire conditional hierarchy up until the first non-conditional parent
126
- var conditionalContext = unconditionalFragmentContext . GetOrCreateConditionalContext ( conditional ) ;
209
+ var conditionalContext = unconditionalFragmentContext . GetOrCreateConditionalContext ( Conditional ) ;
127
210
128
211
return conditionalContext ;
129
212
}
0 commit comments