diff --git a/build.gradle b/build.gradle index 29c6f8d304f..7cf869227dc 100644 --- a/build.gradle +++ b/build.gradle @@ -106,6 +106,10 @@ allprojects { } } +clean.doFirst { + delete "${rootDir}/build-logic" +} + task(copyTestResources, type: Copy) .from('src/test') .into("$buildDir/classes/test") diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java index cd354a596f2..50103d5348f 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java @@ -24,7 +24,6 @@ import org.codehaus.groovy.ast.ClassNode; import org.codehaus.groovy.ast.GenericsType; import org.codehaus.groovy.ast.GenericsType.GenericsTypeName; -import org.codehaus.groovy.ast.InnerClassNode; import org.codehaus.groovy.ast.MethodNode; import org.codehaus.groovy.ast.Parameter; import org.codehaus.groovy.ast.Variable; @@ -2033,24 +2032,22 @@ private static Map mergeGenerics(Map filterMethodsByVisibility(final List methodNodeList, final ClassNode enclosingClassNode) { if (!asBoolean(methodNodeList)) { - return StaticTypeCheckingVisitor.EMPTY_METHODNODE_LIST; + return Collections.emptyList(); } List result = new LinkedList<>(); + List< ClassNode> outers = enclosingClassNode.getOuterClasses(); - boolean isEnclosingInnerClass = enclosingClassNode instanceof InnerClassNode; - List outerClasses = enclosingClassNode.getOuterClasses(); - - outer: + next_method: for (MethodNode methodNode : methodNodeList) { if (methodNode instanceof ExtensionMethodNode) { result.add(methodNode); @@ -2059,23 +2056,23 @@ public static List filterMethodsByVisibility(final List ClassNode declaringClass = methodNode.getDeclaringClass(); - if (isEnclosingInnerClass) { - for (ClassNode outerClass : outerClasses) { + if (asBoolean(outers)) { + for (ClassNode outerClass : outers) { if (outerClass.isDerivedFrom(declaringClass)) { if (outerClass.equals(declaringClass)) { result.add(methodNode); - continue outer; + continue next_method; } else { if (methodNode.isPublic() || methodNode.isProtected()) { result.add(methodNode); - continue outer; + continue next_method; } } } } } - if (declaringClass instanceof InnerClassNode) { + if (declaringClass.getOuterClass() != null) { if (declaringClass.getOuterClasses().contains(enclosingClassNode)) { result.add(methodNode); continue; 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 5313e58915a..eb162daf8d6 100644 --- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -1460,7 +1460,7 @@ protected boolean existsProperty(final PropertyExpression pexp, final boolean ch protected boolean existsProperty(final PropertyExpression pexp, final boolean readMode, final ClassCodeVisitorSupport visitor) { super.visitPropertyExpression(pexp); - String propertyName = pexp.getPropertyAsString(); + final String propertyName = pexp.getPropertyAsString(); if (propertyName == null) return false; Expression objectExpression = pexp.getObjectExpression(); @@ -1613,7 +1613,7 @@ protected boolean existsProperty(final PropertyExpression pexp, final boolean re if (field != null && storeField(field, pexp, receiverType, visitor, receiver.getData(), !readMode)) return true; - foundGetterOrSetter = (foundGetterOrSetter || !setters.isEmpty() || getter != null); + foundGetterOrSetter = (foundGetterOrSetter || getter != null || !setters.isEmpty()); } // GROOVY-5568: the property may be defined by DGM diff --git a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy index 15122ed9299..7edaea09c0f 100644 --- a/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy +++ b/src/test/groovy/transform/stc/FieldsAndPropertiesSTCTest.groovy @@ -195,8 +195,44 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase { 'No such property: x for class: C' } + // GROOVY-11319 @NotYetImplemented void testShouldComplainAboutMissingProperty3() { + shouldFailWithMessages ''' + class C { + private int getX() { 1 } + } + class D extends C { + void test() { + super.x + } + } + new D().test() + ''', + 'No such property: x for class: C' + } + + // GROOVY-11319 + @NotYetImplemented + void testShouldComplainAboutMissingProperty4() { + shouldFailWithMessages ''' + class C { + private void setX(int i) { + assert false : 'cannot access' + } + } + class D extends C { + void test() { + super.x = 1 + } + } + new D().test() + ''', + 'No such property: x for class: C' + } + + @NotYetImplemented + void testShouldComplainAboutMissingProperty5() { shouldFailWithMessages ''' class C { private x @@ -206,8 +242,9 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase { this.x } } + new D().test() ''', - 'Cannot access field: x of class: C' + 'No such property: x for class: D' } void testShouldComplainAboutMissingAttribute() { @@ -624,16 +661,22 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase { ''' } + // GROOVY-5988 void testMapPropertyAccess3() { assertScript ''' - String key = 'foo' - Map map = [(key): 123] + String key = 'name' + Map map = [:] + map[key] = 123 @ASTTest(phase=INSTRUCTION_SELECTION, value={ assert node.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE }) def val = map[key] assert val == 123 ''' + assertScript ''' + def names = [:].getProperties().keySet() + assert names.toSorted() == ['class', 'empty'] // TODO: remove? + ''' } // GROOVY-5797 @@ -777,7 +820,7 @@ class FieldsAndPropertiesSTCTest extends StaticTypeCheckingTestCase { assert map.metaClass == null ''' assertScript type + ''' - def test(C map) { + def test(C map) { // no diff assert map.entry == null assert map.empty == null assert map.class == null