@@ -365,16 +365,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
365
365
366
366
public static final Statement GENERATED_EMPTY_STATEMENT = EmptyStatement .INSTANCE ;
367
367
368
- protected final ReturnAdder .ReturnStatementListener returnListener = new ReturnAdder .ReturnStatementListener () {
369
- @ Override
370
- public void returnStatementAdded (final ReturnStatement returnStatement ) {
371
- if (isNullConstant (returnStatement .getExpression ())) return ;
372
- ClassNode returnType = checkReturnType (returnStatement );
373
- if (typeCheckingContext .getEnclosingClosure () != null ) {
374
- addClosureReturnType (returnType );
375
- } else if (typeCheckingContext .getEnclosingMethod () == null ) {
376
- throw new GroovyBugError ("Unexpected return statement at " + returnStatement .getLineNumber () + ":" + returnStatement .getColumnNumber () + " " + returnStatement .getText ());
377
- }
368
+ protected final ReturnAdder .ReturnStatementListener returnListener = returnStatement -> {
369
+ if (returnStatement .isReturningNullOrVoid ()) return ;
370
+ ClassNode returnType = checkReturnType (returnStatement );
371
+ if (this .typeCheckingContext .getEnclosingClosure () != null ) {
372
+ addClosureReturnType (returnType );
373
+ } else if (this .typeCheckingContext .getEnclosingMethod () == null ) {
374
+ throw new GroovyBugError ("Unexpected return statement at " + returnStatement .getLineNumber () + ":" + returnStatement .getColumnNumber () + " " + returnStatement .getText ());
378
375
}
379
376
};
380
377
@@ -792,11 +789,7 @@ public void visitBinaryExpression(final BinaryExpression expression) {
792
789
} else {
793
790
lType = getOriginalDeclarationType (leftExpression );
794
791
795
- if (isFunctionalInterface (lType )) {
796
- processFunctionalInterfaceAssignment (lType , rightExpression );
797
- } else if (isClosureWithType (lType ) && rightExpression instanceof ClosureExpression ) {
798
- storeInferredReturnType (rightExpression , getCombinedBoundType (lType .getGenericsTypes ()[0 ]));
799
- }
792
+ applyTargetType (lType , rightExpression );
800
793
}
801
794
rightExpression .visit (this );
802
795
}
@@ -965,15 +958,22 @@ private void validateResourceInARM(final BinaryExpression expression, final Clas
965
958
}
966
959
}
967
960
968
- private void processFunctionalInterfaceAssignment (final ClassNode lhsType , final Expression rhsExpression ) {
969
- if (rhsExpression instanceof ClosureExpression ) {
970
- inferParameterAndReturnTypesOfClosureOnRHS (lhsType , (ClosureExpression ) rhsExpression );
971
- } else if (rhsExpression instanceof MethodReferenceExpression ) {
972
- LambdaExpression lambdaExpression = constructLambdaExpressionForMethodReference (lhsType );
961
+ private void applyTargetType (final ClassNode target , final Expression source ) {
962
+ if (isFunctionalInterface (target )) {
963
+ if (source instanceof ClosureExpression ) {
964
+ inferParameterAndReturnTypesOfClosureOnRHS (target , (ClosureExpression ) source );
965
+ } else if (source instanceof MethodReferenceExpression ) {
966
+ LambdaExpression lambdaExpression = constructLambdaExpressionForMethodReference (target );
973
967
974
- inferParameterAndReturnTypesOfClosureOnRHS (lhsType , lambdaExpression );
975
- rhsExpression .putNodeMetaData (CONSTRUCTED_LAMBDA_EXPRESSION , lambdaExpression );
976
- rhsExpression .putNodeMetaData (CLOSURE_ARGUMENTS , Arrays .stream (lambdaExpression .getParameters ()).map (Parameter ::getType ).toArray (ClassNode []::new ));
968
+ inferParameterAndReturnTypesOfClosureOnRHS (target , lambdaExpression );
969
+ source .putNodeMetaData (CONSTRUCTED_LAMBDA_EXPRESSION , lambdaExpression );
970
+ source .putNodeMetaData (CLOSURE_ARGUMENTS , Arrays .stream (lambdaExpression .getParameters ()).map (Parameter ::getType ).toArray (ClassNode []::new ));
971
+ }
972
+ } else if (isClosureWithType (target )) {
973
+ if (source instanceof ClosureExpression ) {
974
+ GenericsType returnType = target .getGenericsTypes ()[0 ];
975
+ storeInferredReturnType (source , getCombinedBoundType (returnType ));
976
+ }
977
977
}
978
978
}
979
979
@@ -1970,11 +1970,7 @@ public void visitField(final FieldNode node) {
1970
1970
private void visitInitialExpression (final Expression value , final Expression target , final ASTNode position ) {
1971
1971
if (value != null ) {
1972
1972
ClassNode lType = target .getType ();
1973
- if (isFunctionalInterface (lType )) { // GROOVY-9977
1974
- processFunctionalInterfaceAssignment (lType , value );
1975
- } else if (isClosureWithType (lType ) && value instanceof ClosureExpression ) {
1976
- storeInferredReturnType (value , getCombinedBoundType (lType .getGenericsTypes ()[0 ]));
1977
- }
1973
+ applyTargetType (lType , value ); // GROOVY-9977
1978
1974
1979
1975
typeCheckingContext .pushEnclosingBinaryExpression (assignX (target , value , position ));
1980
1976
@@ -2244,6 +2240,12 @@ public void visitExpressionStatement(final ExpressionStatement statement) {
2244
2240
2245
2241
@ Override
2246
2242
public void visitReturnStatement (final ReturnStatement statement ) {
2243
+ if (typeCheckingContext .getEnclosingClosure () == null ) {
2244
+ MethodNode method = typeCheckingContext .getEnclosingMethod ();
2245
+ if (method != null && !method .isVoidMethod () && !method .isDynamicReturnType ()) {
2246
+ applyTargetType (method .getReturnType (), statement .getExpression ()); // GROOVY-10660
2247
+ }
2248
+ }
2247
2249
super .visitReturnStatement (statement );
2248
2250
returnListener .returnStatementAdded (statement );
2249
2251
}
@@ -2631,6 +2633,10 @@ protected void startMethodInference(final MethodNode node, final ErrorCollector
2631
2633
@ Override
2632
2634
protected void visitConstructorOrMethod (final MethodNode node , final boolean isConstructor ) {
2633
2635
typeCheckingContext .pushEnclosingMethod (node );
2636
+ final ClassNode returnType = node .getReturnType (); // GROOVY-10660: implicit return case
2637
+ if (!isConstructor && (isClosureWithType (returnType ) || isFunctionalInterface (returnType ))) {
2638
+ new ReturnAdder (returnStmt -> applyTargetType (returnType , returnStmt .getExpression ())).visitMethod (node );
2639
+ }
2634
2640
readClosureParameterAnnotation (node ); // GROOVY-6603
2635
2641
super .visitConstructorOrMethod (node , isConstructor );
2636
2642
if (node .hasDefaultValue ()) {
@@ -4168,18 +4174,14 @@ public void visitArrayExpression(final ArrayExpression expression) {
4168
4174
4169
4175
@ Override
4170
4176
public void visitCastExpression (final CastExpression expression ) {
4171
- ClassNode type = expression .getType ();
4177
+ ClassNode target = expression .getType ();
4172
4178
Expression source = expression .getExpression ();
4173
- if (isFunctionalInterface (type )) { // GROOVY-9997
4174
- processFunctionalInterfaceAssignment (type , source );
4175
- } else if (isClosureWithType (type ) && source instanceof ClosureExpression ) {
4176
- storeInferredReturnType (source , getCombinedBoundType (type .getGenericsTypes ()[0 ]));
4177
- }
4179
+ applyTargetType (target , source ); // GROOVY-9997
4178
4180
4179
4181
source .visit (this );
4180
4182
4181
- if (!expression .isCoerce () && !checkCast (type , source )) {
4182
- addStaticTypeError ("Inconvertible types: cannot cast " + prettyPrintType (getType (source )) + " to " + prettyPrintType (type ), expression );
4183
+ if (!expression .isCoerce () && !checkCast (target , source )) {
4184
+ addStaticTypeError ("Inconvertible types: cannot cast " + prettyPrintType (getType (source )) + " to " + prettyPrintType (target ), expression );
4183
4185
}
4184
4186
}
4185
4187
@@ -5999,19 +6001,16 @@ private class ParameterVariableExpression extends VariableExpression {
5999
6001
ParameterVariableExpression (final Parameter parameter ) {
6000
6002
super (parameter );
6001
6003
this .parameter = parameter ;
6002
- /* GRECLIPSE edit -- GROOVY-10651
6003
- this.parameter.getNodeMetaData(INFERRED_TYPE, x -> parameter.getOriginType());
6004
- */
6004
+
6005
6005
ClassNode inferredType = getNodeMetaData (INFERRED_TYPE );
6006
6006
if (inferredType == null ) {
6007
6007
inferredType = typeCheckingContext .controlStructureVariables .get (parameter ); // for/catch/closure
6008
6008
if (inferredType == null ) {
6009
6009
TypeCheckingContext .EnclosingClosure enclosingClosure = typeCheckingContext .getEnclosingClosure ();
6010
6010
if (enclosingClosure != null ) inferredType = getTypeFromClosureArguments (parameter , enclosingClosure );
6011
6011
}
6012
- setNodeMetaData (INFERRED_TYPE , inferredType != null ? inferredType : parameter .getType ()); // to parameter
6012
+ setNodeMetaData (INFERRED_TYPE , inferredType != null ? inferredType : parameter .getType ()); // GROOVY-10651
6013
6013
}
6014
- // GRECLIPSE end
6015
6014
}
6016
6015
6017
6016
@ Override
0 commit comments