29
29
import static org .jetbrains .kotlin .resolve .calls .smartcasts .Nullability .NOT_NULL ;
30
30
31
31
/* package */ class DelegatingDataFlowInfo implements DataFlowInfo {
32
- private static final ImmutableMap <DataFlowValue ,Nullability > EMPTY_NULLABILITY_INFO = ImmutableMap .of ();
32
+ private static final ImmutableMap <DataFlowValue , Nullability > EMPTY_NULLABILITY_INFO = ImmutableMap .of ();
33
33
private static final SetMultimap <DataFlowValue , JetType > EMPTY_TYPE_INFO = newTypeInfo ();
34
34
private static final DataFlowInfo EMPTY_INFO_WITH_JUMP = new DelegatingDataFlowInfo (null , EMPTY_NULLABILITY_INFO ,
35
35
EMPTY_TYPE_INFO , true );
40
40
@ NotNull
41
41
private final ImmutableMap <DataFlowValue , Nullability > nullabilityInfo ;
42
42
43
- /** Also immutable */
43
+ /**
44
+ * Also immutable
45
+ */
44
46
@ NotNull
45
47
private final SetMultimap <DataFlowValue , JetType > typeInfo ;
46
48
49
+ /**
50
+ * Value for which type info was cleared at this point
51
+ * so parent type info should not be in use
52
+ */
53
+ @ Nullable
54
+ private final DataFlowValue valueWithoutTypeInfo ;
55
+
47
56
private final boolean jumpPossible ;
48
57
49
58
/* package */ DelegatingDataFlowInfo (
50
59
@ Nullable DataFlowInfo parent ,
51
60
@ NotNull ImmutableMap <DataFlowValue , Nullability > nullabilityInfo ,
52
61
@ NotNull SetMultimap <DataFlowValue , JetType > typeInfo ,
53
62
boolean jumpPossible
63
+ ) {
64
+ this (parent , nullabilityInfo , typeInfo , jumpPossible , null );
65
+ }
66
+
67
+ /* package */ DelegatingDataFlowInfo (
68
+ @ Nullable DataFlowInfo parent ,
69
+ @ NotNull ImmutableMap <DataFlowValue , Nullability > nullabilityInfo ,
70
+ @ NotNull SetMultimap <DataFlowValue , JetType > typeInfo ,
71
+ boolean jumpPossible ,
72
+ @ Nullable DataFlowValue valueWithoutTypeInfo
54
73
) {
55
74
this .parent = parent ;
56
75
this .nullabilityInfo = nullabilityInfo ;
57
76
this .typeInfo = typeInfo ;
58
77
this .jumpPossible = jumpPossible ;
78
+ this .valueWithoutTypeInfo = valueWithoutTypeInfo ;
59
79
}
60
80
61
81
@ Override
@@ -80,10 +100,16 @@ public Map<DataFlowValue, Nullability> getCompleteNullabilityInfo() {
80
100
@ NotNull
81
101
public SetMultimap <DataFlowValue , JetType > getCompleteTypeInfo () {
82
102
SetMultimap <DataFlowValue , JetType > result = newTypeInfo ();
103
+ Set <DataFlowValue > resultCompleted = new LinkedHashSet <DataFlowValue >();
83
104
DelegatingDataFlowInfo info = this ;
84
105
while (info != null ) {
85
106
for (DataFlowValue key : info .typeInfo .keySet ()) {
86
- result .putAll (key , info .typeInfo .get (key ));
107
+ if (!resultCompleted .contains (key )) {
108
+ result .putAll (key , info .typeInfo .get (key ));
109
+ }
110
+ }
111
+ if (valueWithoutTypeInfo != null ) {
112
+ resultCompleted .add (valueWithoutTypeInfo );
87
113
}
88
114
info = (DelegatingDataFlowInfo ) info .parent ;
89
115
}
@@ -105,19 +131,25 @@ public Nullability getNullability(@NotNull DataFlowValue key) {
105
131
key .getImmanentNullability ();
106
132
}
107
133
108
- private boolean putNullability (@ NotNull Map <DataFlowValue , Nullability > map , @ NotNull DataFlowValue value , @ NotNull Nullability nullability ) {
134
+ private boolean putNullability (
135
+ @ NotNull Map <DataFlowValue , Nullability > map ,
136
+ @ NotNull DataFlowValue value ,
137
+ @ NotNull Nullability nullability
138
+ ) {
109
139
if (!value .isStableIdentifier () && !value .isLocalVariable ()) return false ;
110
140
map .put (value , nullability );
111
141
return nullability != getNullability (value );
112
142
}
113
143
114
144
@ NotNull
115
145
private Set <JetType > getDirectlyPossibleTypes (@ NotNull DataFlowValue key ) {
146
+ if (key == valueWithoutTypeInfo ) {
147
+ return EMPTY_TYPE_INFO .get (key );
148
+ }
116
149
Set <JetType > theseTypes = typeInfo .get (key );
117
- Set <JetType > types = parent instanceof DelegatingDataFlowInfo ?
118
- Sets .union (theseTypes , ((DelegatingDataFlowInfo )parent ).getDirectlyPossibleTypes (key )) :
119
- theseTypes ;
120
- return types ;
150
+ return parent instanceof DelegatingDataFlowInfo ?
151
+ Sets .union (theseTypes , ((DelegatingDataFlowInfo ) parent ).getDirectlyPossibleTypes (key )) :
152
+ theseTypes ;
121
153
}
122
154
123
155
@ Override
@@ -140,6 +172,30 @@ public Set<JetType> getPossibleTypes(@NotNull DataFlowValue key) {
140
172
return enrichedTypes ;
141
173
}
142
174
175
+ /**
176
+ * Call this function to clear all data flow information about
177
+ * the given data flow value.
178
+ *
179
+ * @param value
180
+ */
181
+ @ NotNull
182
+ @ Override
183
+ public DataFlowInfo clearValueInfo (@ NotNull DataFlowValue value ) {
184
+ Map <DataFlowValue , Nullability > builder = Maps .newHashMap ();
185
+ boolean changed = putNullability (builder , value , Nullability .UNKNOWN );
186
+ // We want to clear all these types
187
+ changed |= !getDirectlyPossibleTypes (value ).isEmpty ();
188
+ return !changed
189
+ ? this
190
+ : new DelegatingDataFlowInfo (
191
+ this ,
192
+ ImmutableMap .copyOf (builder ),
193
+ EMPTY_TYPE_INFO ,
194
+ jumpPossible ,
195
+ value
196
+ );
197
+ }
198
+
143
199
@ NotNull
144
200
@ Override
145
201
public DataFlowInfo assign (@ NotNull DataFlowValue a , @ NotNull DataFlowValue b ) {
@@ -177,13 +233,13 @@ public DataFlowInfo equate(@NotNull DataFlowValue a, @NotNull DataFlowValue b) {
177
233
changed |= !newTypeInfo .isEmpty ();
178
234
179
235
return !changed
180
- ? this
181
- : new DelegatingDataFlowInfo (
182
- this ,
183
- ImmutableMap .copyOf (builder ),
184
- newTypeInfo .isEmpty () ? EMPTY_TYPE_INFO : newTypeInfo ,
185
- jumpPossible
186
- );
236
+ ? this
237
+ : new DelegatingDataFlowInfo (
238
+ this ,
239
+ ImmutableMap .copyOf (builder ),
240
+ newTypeInfo .isEmpty () ? EMPTY_TYPE_INFO : newTypeInfo ,
241
+ jumpPossible
242
+ );
187
243
}
188
244
189
245
@ NotNull
@@ -254,7 +310,7 @@ public DataFlowInfo and(@NotNull DataFlowInfo otherInfo) {
254
310
SetMultimap <DataFlowValue , JetType > myTypeInfo = getCompleteTypeInfo ();
255
311
SetMultimap <DataFlowValue , JetType > otherTypeInfo = other .getCompleteTypeInfo ();
256
312
if (nullabilityMapBuilder .isEmpty () && containsAll (myTypeInfo , otherTypeInfo )) {
257
- return otherInfo .isJumpPossible () ? jump (): this ;
313
+ return otherInfo .isJumpPossible () ? jump () : this ;
258
314
}
259
315
260
316
return new DelegatingDataFlowInfo (this , ImmutableMap .copyOf (nullabilityMapBuilder ), otherTypeInfo ,
@@ -297,7 +353,8 @@ public DataFlowInfo or(@NotNull DataFlowInfo otherInfo) {
297
353
return (jumpPossible || otherInfo .isJumpPossible ()) ? EMPTY_INFO_WITH_JUMP : EMPTY ;
298
354
}
299
355
300
- return new DelegatingDataFlowInfo (null , ImmutableMap .copyOf (nullabilityMapBuilder ), newTypeInfo , jumpPossible || otherInfo .isJumpPossible ());
356
+ return new DelegatingDataFlowInfo (null , ImmutableMap .copyOf (nullabilityMapBuilder ), newTypeInfo ,
357
+ jumpPossible || otherInfo .isJumpPossible ());
301
358
}
302
359
303
360
@ NotNull
0 commit comments