@@ -768,11 +768,7 @@ public void visitBinaryExpression(final BinaryExpression expression) {
768
768
} else {
769
769
lType = getOriginalDeclarationType (leftExpression );
770
770
771
- if (isFunctionalInterface (lType )) {
772
- processFunctionalInterfaceAssignment (lType , rightExpression );
773
- } else if (isClosureWithType (lType ) && rightExpression instanceof ClosureExpression ) {
774
- storeInferredReturnType (rightExpression , getCombinedBoundType (lType .getGenericsTypes ()[0 ]));
775
- }
771
+ applyTargetType (lType , rightExpression );
776
772
}
777
773
rightExpression .visit (this );
778
774
}
@@ -908,21 +904,28 @@ private void validateResourceInARM(final BinaryExpression expression, final Clas
908
904
}
909
905
}
910
906
911
- private void processFunctionalInterfaceAssignment (final ClassNode lhsType , final Expression rhsExpression ) {
912
- if (rhsExpression instanceof ClosureExpression ) {
913
- inferParameterAndReturnTypesOfClosureOnRHS (lhsType , (ClosureExpression ) rhsExpression );
914
- } else if (rhsExpression instanceof MapExpression ) { // GROOVY-7141
915
- List <MapEntryExpression > spec = ((MapExpression ) rhsExpression ).getMapEntryExpressions ();
916
- if (spec .size () == 1 && spec .get (0 ).getValueExpression () instanceof ClosureExpression
917
- && findSAM (lhsType ).getName ().equals (spec .get (0 ).getKeyExpression ().getText ())) {
918
- inferParameterAndReturnTypesOfClosureOnRHS (lhsType , (ClosureExpression ) spec .get (0 ).getValueExpression ());
907
+ private void applyTargetType (final ClassNode target , final Expression source ) {
908
+ if (isClosureWithType (target )) {
909
+ if (source instanceof ClosureExpression ) {
910
+ GenericsType returnType = target .getGenericsTypes ()[0 ];
911
+ storeInferredReturnType (source , getCombinedBoundType (returnType ));
919
912
}
920
- } else if (rhsExpression instanceof MethodReferenceExpression ) {
921
- LambdaExpression lambdaExpression = constructLambdaExpressionForMethodReference (lhsType , (MethodReferenceExpression ) rhsExpression );
913
+ } else if (isFunctionalInterface (target )) {
914
+ if (source instanceof ClosureExpression ) {
915
+ inferParameterAndReturnTypesOfClosureOnRHS (target , (ClosureExpression ) source );
916
+ } else if (source instanceof MapExpression ) { // GROOVY-7141
917
+ List <MapEntryExpression > spec = ((MapExpression ) source ).getMapEntryExpressions ();
918
+ if (spec .size () == 1 && spec .get (0 ).getValueExpression () instanceof ClosureExpression
919
+ && findSAM (target ).getName ().equals (spec .get (0 ).getKeyExpression ().getText ())) {
920
+ inferParameterAndReturnTypesOfClosureOnRHS (target , (ClosureExpression ) spec .get (0 ).getValueExpression ());
921
+ }
922
+ } else if (source instanceof MethodReferenceExpression ) {
923
+ LambdaExpression lambda = constructLambdaExpressionForMethodReference (target , (MethodReferenceExpression ) source );
922
924
923
- inferParameterAndReturnTypesOfClosureOnRHS (lhsType , lambdaExpression );
924
- rhsExpression .putNodeMetaData (CONSTRUCTED_LAMBDA_EXPRESSION , lambdaExpression );
925
- rhsExpression .putNodeMetaData (CLOSURE_ARGUMENTS , Arrays .stream (lambdaExpression .getParameters ()).map (Parameter ::getType ).toArray (ClassNode []::new ));
925
+ inferParameterAndReturnTypesOfClosureOnRHS (target , lambda );
926
+ source .putNodeMetaData (CONSTRUCTED_LAMBDA_EXPRESSION , lambda );
927
+ source .putNodeMetaData (CLOSURE_ARGUMENTS , extractTypesFromParameters (lambda .getParameters ()));
928
+ }
926
929
}
927
930
}
928
931
@@ -1952,16 +1955,12 @@ public void visitField(final FieldNode node) {
1952
1955
}
1953
1956
}
1954
1957
1955
- private void visitInitialExpression (final Expression value , final Expression target , final ASTNode position ) {
1958
+ private void visitInitialExpression (final Expression value , final Expression target , final ASTNode origin ) {
1956
1959
if (value != null ) {
1957
1960
ClassNode lType = target .getType ();
1958
- if (isFunctionalInterface (lType )) { // GROOVY-9977
1959
- processFunctionalInterfaceAssignment (lType , value );
1960
- } else if (isClosureWithType (lType ) && value instanceof ClosureExpression ) {
1961
- storeInferredReturnType (value , getCombinedBoundType (lType .getGenericsTypes ()[0 ]));
1962
- }
1961
+ applyTargetType (lType , value ); // GROOVY-9977
1963
1962
1964
- typeCheckingContext .pushEnclosingBinaryExpression (assignX (target , value , position ));
1963
+ typeCheckingContext .pushEnclosingBinaryExpression (assignX (target , value , origin ));
1965
1964
1966
1965
value .visit (this );
1967
1966
ClassNode rType = getType (value );
@@ -4215,18 +4214,14 @@ public void visitArrayExpression(final ArrayExpression expression) {
4215
4214
4216
4215
@ Override
4217
4216
public void visitCastExpression (final CastExpression expression ) {
4218
- ClassNode type = expression .getType ();
4219
- Expression target = expression .getExpression ();
4220
- if (isFunctionalInterface (type )) { // GROOVY-9997
4221
- processFunctionalInterfaceAssignment (type , target );
4222
- } else if (isClosureWithType (type ) && target instanceof ClosureExpression ) {
4223
- storeInferredReturnType (target , getCombinedBoundType (type .getGenericsTypes ()[0 ]));
4224
- }
4217
+ ClassNode target = expression .getType ();
4218
+ Expression source = expression .getExpression ();
4219
+ applyTargetType (target , source ); // GROOVY-9997
4225
4220
4226
- target .visit (this );
4221
+ source .visit (this );
4227
4222
4228
- if (!expression .isCoerce () && !checkCast (type , target ) && !isDelegateOrOwnerInClosure (target )) {
4229
- addStaticTypeError ("Inconvertible types: cannot cast " + prettyPrintType (getType (target )) + " to " + prettyPrintType (type ), expression );
4223
+ if (!expression .isCoerce () && !checkCast (target , source ) && !isDelegateOrOwnerInClosure (source )) {
4224
+ addStaticTypeError ("Inconvertible types: cannot cast " + prettyPrintType (getType (source )) + " to " + prettyPrintType (target ), expression );
4230
4225
}
4231
4226
}
4232
4227
@@ -4273,12 +4268,10 @@ public void visitTernaryExpression(final TernaryExpression expression) {
4273
4268
}
4274
4269
Expression trueExpression = expression .getTrueExpression ();
4275
4270
ClassNode typeOfTrue = findCurrentInstanceOfClass (trueExpression , null );
4276
- trueExpression .visit (this );
4277
- if (typeOfTrue == null ) typeOfTrue = getType (trueExpression );
4271
+ typeOfTrue = Optional .ofNullable (typeOfTrue ).orElse (visitValueExpression (trueExpression ));
4278
4272
typeCheckingContext .popTemporaryTypeInfo (); // instanceof doesn't apply to false branch
4279
4273
Expression falseExpression = expression .getFalseExpression ();
4280
- falseExpression .visit (this );
4281
- ClassNode typeOfFalse = getType (falseExpression );
4274
+ ClassNode typeOfFalse = visitValueExpression (falseExpression );
4282
4275
4283
4276
ClassNode resultType ;
4284
4277
if (isNullConstant (trueExpression ) && isNullConstant (falseExpression )) { // GROOVY-5523
@@ -4298,6 +4291,18 @@ && isOrImplements(typeOfFalse, typeOfTrue))) { // List/Collection/Iterable : []
4298
4291
popAssignmentTracking (oldTracker );
4299
4292
}
4300
4293
4294
+ /**
4295
+ * @param expr true or false branch of ternary expression
4296
+ * @return the inferred type of {@code expr}
4297
+ */
4298
+ private ClassNode visitValueExpression (final Expression expr ) {
4299
+ if (expr instanceof ClosureExpression ) {
4300
+ applyTargetType (checkForTargetType (expr , null ), expr );
4301
+ }
4302
+ expr .visit (this );
4303
+ return getType (expr );
4304
+ }
4305
+
4301
4306
/**
4302
4307
* @param expr true or false branch of ternary expression
4303
4308
* @param type the inferred type of {@code expr}
@@ -4322,6 +4327,10 @@ && isTypeSource(expr, enclosingMethod)) {
4322
4327
targetType = enclosingMethod .getReturnType ();
4323
4328
}
4324
4329
4330
+ if (expr instanceof ClosureExpression ) { // GROOVY-10271, GROOVY-10272
4331
+ return isSAMType (targetType ) ? targetType : type ;
4332
+ }
4333
+
4325
4334
if (targetType == null )
4326
4335
targetType = type .getPlainNodeReference ();
4327
4336
if (type == UNKNOWN_PARAMETER_TYPE ) return targetType ;
@@ -4351,7 +4360,7 @@ && missesGenericsTypes(resultType)
4351
4360
// GROOVY-6126, GROOVY-6558, GROOVY-6564, et al.
4352
4361
if (!targetType .isGenericsPlaceHolder ()) return targetType ;
4353
4362
} else {
4354
- // GROOVY-5640, GROOVY-9033, GROOVY-10220, GROOVY-10235, GROOVY-10688, et al.
4363
+ // GROOVY-5640, GROOVY-9033, GROOVY-10220, GROOVY-10235, GROOVY-10688, GROOVY-11192, et al.
4355
4364
Map <GenericsTypeName , GenericsType > gt = new HashMap <>();
4356
4365
ClassNode sc = resultType ;
4357
4366
for (;;) {
0 commit comments