@@ -305,10 +305,8 @@ class TypeInferrerImpl implements TypeInferrer {
305
305
/// Computes a list of context messages explaining why [receiver] was not
306
306
/// promoted, to be used when reporting an error for a larger expression
307
307
/// containing [receiver] . [expression] is the containing expression.
308
- List <LocatedMessage > getWhyNotPromotedContext (
309
- Expression receiver, Expression expression) {
310
- Map <DartType , NonPromotionReason > whyNotPromoted =
311
- flowAnalysis? .whyNotPromoted (receiver);
308
+ List <LocatedMessage > getWhyNotPromotedContext (Expression receiver,
309
+ Map <DartType , NonPromotionReason > whyNotPromoted, Expression expression) {
312
310
List <LocatedMessage > context;
313
311
if (whyNotPromoted != null && whyNotPromoted.isNotEmpty) {
314
312
_WhyNotPromotedVisitor whyNotPromotedVisitor =
@@ -2755,12 +2753,22 @@ class TypeInferrerImpl implements TypeInferrer {
2755
2753
implicitInvocationPropertyName: name);
2756
2754
2757
2755
if (! isTopLevel && target.isNullable) {
2756
+ // Handles cases like:
2757
+ // C? c;
2758
+ // c();
2759
+ // where there is an extension on C defined as:
2760
+ // extension on C {
2761
+ // void Function() get call => () {};
2762
+ // }
2763
+ List <LocatedMessage > context = getWhyNotPromotedContext (
2764
+ receiver, flowAnalysis? .whyNotPromoted (receiver), staticInvocation);
2758
2765
result = wrapExpressionInferenceResultInProblem (
2759
2766
result,
2760
2767
templateNullableExpressionCallError.withArguments (
2761
2768
receiverType, isNonNullableByDefault),
2762
2769
fileOffset,
2763
- noLength);
2770
+ noLength,
2771
+ context: context);
2764
2772
}
2765
2773
2766
2774
return result;
@@ -2780,13 +2788,23 @@ class TypeInferrerImpl implements TypeInferrer {
2780
2788
2781
2789
Expression replacement = result.applyResult (staticInvocation);
2782
2790
if (! isTopLevel && target.isNullable) {
2791
+ List <LocatedMessage > context = getWhyNotPromotedContext (
2792
+ receiver, flowAnalysis? .whyNotPromoted (receiver), staticInvocation);
2783
2793
if (isImplicitCall) {
2794
+ // Handles cases like:
2795
+ // int? i;
2796
+ // i();
2797
+ // where there is an extension:
2798
+ // extension on int {
2799
+ // void call() {}
2800
+ // }
2784
2801
replacement = helper.wrapInProblem (
2785
2802
replacement,
2786
2803
templateNullableExpressionCallError.withArguments (
2787
2804
receiverType, isNonNullableByDefault),
2788
2805
fileOffset,
2789
- noLength);
2806
+ noLength,
2807
+ context: context);
2790
2808
} else {
2791
2809
// Handles cases like:
2792
2810
// int? i;
@@ -2801,7 +2819,7 @@ class TypeInferrerImpl implements TypeInferrer {
2801
2819
name.text, receiverType, isNonNullableByDefault),
2802
2820
fileOffset,
2803
2821
name.text.length,
2804
- context: getWhyNotPromotedContext (receiver, staticInvocation) );
2822
+ context: context );
2805
2823
}
2806
2824
}
2807
2825
return createNullAwareExpressionInferenceResult (
@@ -2865,13 +2883,19 @@ class TypeInferrerImpl implements TypeInferrer {
2865
2883
}
2866
2884
Expression replacement = result.applyResult (expression);
2867
2885
if (! isTopLevel && target.isNullableCallFunction) {
2886
+ List <LocatedMessage > context = getWhyNotPromotedContext (
2887
+ receiver, flowAnalysis? .whyNotPromoted (receiver), expression);
2868
2888
if (isImplicitCall) {
2889
+ // Handles cases like:
2890
+ // void Function()? f;
2891
+ // f();
2869
2892
replacement = helper.wrapInProblem (
2870
2893
replacement,
2871
2894
templateNullableExpressionCallError.withArguments (
2872
2895
receiverType, isNonNullableByDefault),
2873
2896
fileOffset,
2874
- noLength);
2897
+ noLength,
2898
+ context: context);
2875
2899
} else {
2876
2900
// Handles cases like:
2877
2901
// void Function()? f;
@@ -2882,7 +2906,7 @@ class TypeInferrerImpl implements TypeInferrer {
2882
2906
callName.text, receiverType, isNonNullableByDefault),
2883
2907
fileOffset,
2884
2908
callName.text.length,
2885
- context: getWhyNotPromotedContext (receiver, expression) );
2909
+ context: context );
2886
2910
}
2887
2911
}
2888
2912
// TODO(johnniwinther): Check that type arguments against the bounds.
@@ -3031,13 +3055,23 @@ class TypeInferrerImpl implements TypeInferrer {
3031
3055
3032
3056
replacement = result.applyResult (replacement);
3033
3057
if (! isTopLevel && target.isNullable) {
3058
+ List <LocatedMessage > context = getWhyNotPromotedContext (
3059
+ receiver, flowAnalysis? .whyNotPromoted (receiver), expression);
3034
3060
if (isImplicitCall) {
3061
+ // Handles cases like:
3062
+ // C? c;
3063
+ // c();
3064
+ // Where C is defined as:
3065
+ // class C {
3066
+ // void call();
3067
+ // }
3035
3068
replacement = helper.wrapInProblem (
3036
3069
replacement,
3037
3070
templateNullableExpressionCallError.withArguments (
3038
3071
receiverType, isNonNullableByDefault),
3039
3072
fileOffset,
3040
- noLength);
3073
+ noLength,
3074
+ context: context);
3041
3075
} else {
3042
3076
// Handles cases like:
3043
3077
// int? i;
@@ -3048,7 +3082,7 @@ class TypeInferrerImpl implements TypeInferrer {
3048
3082
methodName.text, receiverType, isNonNullableByDefault),
3049
3083
fileOffset,
3050
3084
methodName.text.length,
3051
- context: getWhyNotPromotedContext (receiver, expression) );
3085
+ context: context );
3052
3086
}
3053
3087
}
3054
3088
@@ -3172,12 +3206,22 @@ class TypeInferrerImpl implements TypeInferrer {
3172
3206
}
3173
3207
3174
3208
if (! isTopLevel && target.isNullable) {
3209
+ // Handles cases like:
3210
+ // C? c;
3211
+ // c.foo();
3212
+ // Where C is defined as:
3213
+ // class C {
3214
+ // void Function() get foo => () {};
3215
+ // }
3216
+ List <LocatedMessage > context = getWhyNotPromotedContext (receiver,
3217
+ flowAnalysis? .whyNotPromoted (receiver), invocationResult.expression);
3175
3218
invocationResult = wrapExpressionInferenceResultInProblem (
3176
3219
invocationResult,
3177
3220
templateNullableExpressionCallError.withArguments (
3178
3221
receiverType, isNonNullableByDefault),
3179
3222
fileOffset,
3180
- noLength);
3223
+ noLength,
3224
+ context: context);
3181
3225
}
3182
3226
3183
3227
if (! library.loader.target.backendTarget.supportsExplicitGetterCalls) {
@@ -3274,6 +3318,14 @@ class TypeInferrerImpl implements TypeInferrer {
3274
3318
receiver = _hoist (receiver, receiverType, hoistedExpressions);
3275
3319
}
3276
3320
3321
+ Map <DartType , NonPromotionReason > whyNotPromotedInfo;
3322
+ if (! isTopLevel && target.isNullable) {
3323
+ // We won't report the error until later (after we have an
3324
+ // invocationResult), but we need to gather "why not promoted" info now,
3325
+ // before we tell flow analysis about the property get.
3326
+ whyNotPromotedInfo = flowAnalysis? .whyNotPromoted (receiver);
3327
+ }
3328
+
3277
3329
Name originalName = field.name;
3278
3330
Expression originalReceiver = receiver;
3279
3331
Member originalTarget = field;
@@ -3297,6 +3349,8 @@ class TypeInferrerImpl implements TypeInferrer {
3297
3349
kind, originalReceiver, originalName,
3298
3350
resultType: calleeType, interfaceTarget: originalTarget)
3299
3351
..fileOffset = fileOffset;
3352
+ flowAnalysis.propertyGet (
3353
+ originalPropertyGet, originalReceiver, originalName.name);
3300
3354
} else {
3301
3355
originalPropertyGet =
3302
3356
new PropertyGet (originalReceiver, originalName, originalTarget)
@@ -3343,12 +3397,25 @@ class TypeInferrerImpl implements TypeInferrer {
3343
3397
}
3344
3398
3345
3399
if (! isTopLevel && target.isNullable) {
3400
+ // Handles cases like:
3401
+ // C? c;
3402
+ // c.foo();
3403
+ // Where C is defined as:
3404
+ // class C {
3405
+ // void Function() foo;
3406
+ // C(this.foo);
3407
+ // }
3408
+ // TODO(paulberry): would it be better to report NullableMethodCallError
3409
+ // in this scenario?
3410
+ List <LocatedMessage > context = getWhyNotPromotedContext (
3411
+ receiver, whyNotPromotedInfo, invocationResult.expression);
3346
3412
invocationResult = wrapExpressionInferenceResultInProblem (
3347
3413
invocationResult,
3348
3414
templateNullableExpressionCallError.withArguments (
3349
3415
receiverType, isNonNullableByDefault),
3350
3416
fileOffset,
3351
- noLength);
3417
+ noLength,
3418
+ context: context);
3352
3419
}
3353
3420
3354
3421
if (! library.loader.target.backendTarget.supportsExplicitGetterCalls) {
0 commit comments