diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 15b9f9d4595..0fab7e01949 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -620,15 +620,17 @@ public void visitVariableExpression(final VariableExpression vexp) { } else if (accessedVariable instanceof FieldNode) { FieldNode accessedField = (FieldNode) accessedVariable; ClassNode temporaryType = getInferredTypeFromTempInfo(vexp, null); // GROOVY-9454 - if (enclosingClosure != null) { - tryVariableExpressionAsProperty(vexp, name); - } else if (getOutermost(accessedField.getDeclaringClass()) == getOutermost(typeCheckingContext.getEnclosingClassNode()) - || !tryVariableExpressionAsProperty(vexp, name)) { // GROOVY-10981: check for property before super class field - checkOrMarkPrivateAccess(vexp, accessedField, typeCheckingContext.isTargetOfEnclosingAssignment(vexp)); - if (temporaryType == null) storeType(vexp, getType(vexp)); - } - if (temporaryType != null && !temporaryType.equals(OBJECT_TYPE)) { - vexp.putNodeMetaData(INFERRED_TYPE, temporaryType); + boolean declaredInScope = (getOutermost(accessedField.getDeclaringClass()) == getOutermost(typeCheckingContext.getEnclosingClassNode()) + && (enclosingClosure == null || accessedField.isStatic())); // GROOVY-9655, GROOVY-9683, GROOVY-9695, GROOVY-9768, GROOVY-11387 + if (declaredInScope || tryVariableExpressionAsProperty(vexp, name)) { // GROOVY-10981: check for property before super class field + if (temporaryType == null) { + storeType(vexp, getType(vexp)); + } else if (!temporaryType.equals(OBJECT_TYPE)) { + vexp.putNodeMetaData(INFERRED_TYPE, temporaryType); + } + if (declaredInScope) { + checkOrMarkPrivateAccess(vexp, accessedField, typeCheckingContext.isTargetOfEnclosingAssignment(vexp)); + } } } else if (accessedVariable instanceof PropertyNode) { // we must be careful, because the property node may be of a wrong type: diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy index 03da00b3228..03b4e72ff65 100644 --- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy +++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy @@ -1020,6 +1020,21 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase { def accept = HttpHeaders.ACCEPT assert accept == 'Accept' ''' + assertScript ''' + class MapSub extends HashMap { + private static final short ANSWER = 42 + def m() { + {-> + @ASTTest(phase=INSTRUCTION_SELECTION, value={ + assert node.getNodeMetaData(INFERRED_TYPE) == short_TYPE + }) + def answer = ANSWER + }() + } + } + Object answer = new MapSub().m() + assert answer == 42 + ''' } void testTypeCheckerDoesNotThinkPropertyIsReadOnly() {