diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java index 4cdb2af58f..a55f115f29 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java @@ -776,4 +776,24 @@ public void testTypeChecked9903() { "that you either use an explicit class or @DelegatesTo.Target with a correct id\n" + "----------\n"); } + + @Test + public void testTypeChecked9907() { + //@formatter:off + String[] sources = { + "Main.groovy", + "@groovy.transform.TypeChecked\n" + + "Integer foo(x) {\n" + + " if (x instanceof Integer) {\n" + + " def bar = { -> return x }\n" + + " return bar.call()\n" + + " }\n" + + " return 0\n" + + "}\n" + + "println(foo(1))\n", + }; + //@formatter:on + + runConformTest(sources, "1"); + } } diff --git a/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 8a2769e103..4e0e11482b 100644 --- a/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -322,9 +322,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { protected final ReturnAdder.ReturnStatementListener returnListener = new ReturnAdder.ReturnStatementListener() { public void returnStatementAdded(final ReturnStatement returnStatement) { if (isNullConstant(returnStatement.getExpression())) return; + /* GRECLIPSE edit -- GROOVY-9907 checkReturnType(returnStatement); if (typeCheckingContext.getEnclosingClosure() != null) { addClosureReturnType(getType(returnStatement.getExpression())); + */ + ClassNode returnType = checkReturnType(returnStatement); + if (typeCheckingContext.getEnclosingClosure() != null) { + addClosureReturnType(returnType); + // GRECLIPSE end } else if (typeCheckingContext.getEnclosingMethod() != null) { } else { throw new GroovyBugError("Unexpected return statement at " @@ -692,7 +698,11 @@ public void visitVariableExpression(VariableExpression vexp) { */ if (!(accessedVariable instanceof DynamicVariable)) { + /* GRECLIPSE edit -- GROOVY-9907 if (typeCheckingContext.getEnclosingClosure() == null) { + */ + { + // GRECLIPSE end VariableExpression variable = null; if (accessedVariable instanceof Parameter) { variable = new ParameterVariableExpression((Parameter) accessedVariable); @@ -2332,6 +2342,7 @@ private ClassNode infer(ClassNode target, ClassNode source) { protected ClassNode checkReturnType(final ReturnStatement statement) { Expression expression = statement.getExpression(); + /* GRECLIPSE edit -- GROOVY-9907 ClassNode type = getType(expression); if (typeCheckingContext.getEnclosingClosure() != null) { @@ -2341,8 +2352,19 @@ protected ClassNode checkReturnType(final ReturnStatement statement) { if ((expression instanceof VariableExpression) && hasInferredReturnType(expression)) { type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE); } + */ + ClassNode type; + if (expression instanceof VariableExpression && hasInferredReturnType(expression)) { + type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE); + } else { + type = getType(expression); + } + if (typeCheckingContext.getEnclosingClosure() != null) { + return type; + } + // GRECLIPSE end MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod(); - if (enclosingMethod != null && typeCheckingContext.getEnclosingClosure() == null) { + if (enclosingMethod != null) { if (!enclosingMethod.isVoidMethod() && !type.equals(void_WRAPPER_TYPE) && !type.equals(VOID_TYPE) diff --git a/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index ab401d03eb..8fab7ad859 100644 --- a/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -334,9 +334,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { @Override public void returnStatementAdded(final ReturnStatement returnStatement) { if (isNullConstant(returnStatement.getExpression())) return; + /* GRECLIPSE edit -- GROOVY-9907 checkReturnType(returnStatement); if (typeCheckingContext.getEnclosingClosure() != null) { addClosureReturnType(getType(returnStatement.getExpression())); + */ + ClassNode returnType = checkReturnType(returnStatement); + if (typeCheckingContext.getEnclosingClosure() != null) { + addClosureReturnType(returnType); + // GRECLIPSE end } else if (typeCheckingContext.getEnclosingMethod() == null) { throw new GroovyBugError("Unexpected return statement at " + returnStatement.getLineNumber() + ":" + returnStatement.getColumnNumber() + " " + returnStatement.getText()); } @@ -630,7 +636,11 @@ public void visitVariableExpression(final VariableExpression vexp) { } } } + /* GRECLIPSE edit -- GROOVY-9907 } else if (enclosingClosure == null) { + */ + } else { + // GRECLIPSE end VariableExpression localVariable; if (accessedVariable instanceof Parameter) { Parameter parameter = (Parameter) accessedVariable; @@ -2161,6 +2171,7 @@ private ClassNode infer(final ClassNode target, final ClassNode source) { protected ClassNode checkReturnType(final ReturnStatement statement) { Expression expression = statement.getExpression(); + /* GRECLIPSE edit -- GROOVY-9907 ClassNode type = getType(expression); if (typeCheckingContext.getEnclosingClosure() != null) { @@ -2170,8 +2181,19 @@ protected ClassNode checkReturnType(final ReturnStatement statement) { if ((expression instanceof VariableExpression) && hasInferredReturnType(expression)) { type = expression.getNodeMetaData(INFERRED_RETURN_TYPE); } + */ + ClassNode type; + if (expression instanceof VariableExpression && hasInferredReturnType(expression)) { + type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE); + } else { + type = getType(expression); + } + if (typeCheckingContext.getEnclosingClosure() != null) { + return type; + } + // GRECLIPSE end MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod(); - if (enclosingMethod != null && typeCheckingContext.getEnclosingClosure() == null) { + if (enclosingMethod != null) { if (!enclosingMethod.isVoidMethod() && !type.equals(void_WRAPPER_TYPE) && !type.equals(VOID_TYPE) diff --git a/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 80e95e5fd4..38edaea7a6 100644 --- a/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -334,9 +334,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport { @Override public void returnStatementAdded(final ReturnStatement returnStatement) { if (isNullConstant(returnStatement.getExpression())) return; + /* GRECLIPSE edit -- GROOVY-9907 checkReturnType(returnStatement); if (typeCheckingContext.getEnclosingClosure() != null) { addClosureReturnType(getType(returnStatement.getExpression())); + */ + ClassNode returnType = checkReturnType(returnStatement); + if (typeCheckingContext.getEnclosingClosure() != null) { + addClosureReturnType(returnType); + // GRECLIPSE end } else if (typeCheckingContext.getEnclosingMethod() == null) { throw new GroovyBugError("Unexpected return statement at " + returnStatement.getLineNumber() + ":" + returnStatement.getColumnNumber() + " " + returnStatement.getText()); } @@ -630,7 +636,11 @@ public void visitVariableExpression(final VariableExpression vexp) { } } } + /* GRECLIPSE edit -- GROOVY-9907 } else if (enclosingClosure == null) { + */ + } else { + // GRECLIPSE end VariableExpression localVariable; if (accessedVariable instanceof Parameter) { Parameter parameter = (Parameter) accessedVariable; @@ -2148,6 +2158,7 @@ private ClassNode infer(final ClassNode target, final ClassNode source) { protected ClassNode checkReturnType(final ReturnStatement statement) { Expression expression = statement.getExpression(); + /* GRECLIPSE edit -- GROOVY-9907 ClassNode type = getType(expression); if (typeCheckingContext.getEnclosingClosure() != null) { @@ -2157,8 +2168,19 @@ protected ClassNode checkReturnType(final ReturnStatement statement) { if ((expression instanceof VariableExpression) && hasInferredReturnType(expression)) { type = expression.getNodeMetaData(INFERRED_RETURN_TYPE); } + */ + ClassNode type; + if (expression instanceof VariableExpression && hasInferredReturnType(expression)) { + type = expression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE); + } else { + type = getType(expression); + } + if (typeCheckingContext.getEnclosingClosure() != null) { + return type; + } + // GRECLIPSE end MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod(); - if (enclosingMethod != null && typeCheckingContext.getEnclosingClosure() == null) { + if (enclosingMethod != null) { if (!enclosingMethod.isVoidMethod() && !type.equals(void_WRAPPER_TYPE) && !type.equals(VOID_TYPE)