Skip to content

Commit 2927b89

Browse files
committed
GROOVY-11319
1 parent 0e247a8 commit 2927b89

File tree

2 files changed

+62
-26
lines changed

2 files changed

+62
-26
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/StaticCompilationTests.java

+14-22
Original file line numberDiff line numberDiff line change
@@ -3682,17 +3682,13 @@ public void testCompileStatic9007or9043_enumConstToPrivate1() {
36823682
};
36833683
//@formatter:on
36843684

3685-
if (!isAtLeastGroovy(40)) {
3686-
runConformTest(sources, "", "groovy.lang.MissingPropertyException: No such property: name for class: E");
3687-
} else {
3688-
runNegativeTest(sources,
3689-
"----------\n" +
3690-
"1. ERROR in Main.groovy (at line 6)\n" +
3691-
"\tprint E.ONE.name\n" +
3692-
"\t ^^^^^^^^^^\n" +
3693-
"Groovy:[Static type checking] - No such property: name for class: E\n" +
3694-
"----------\n");
3695-
}
3685+
runNegativeTest(sources,
3686+
"----------\n" +
3687+
"1. ERROR in Main.groovy (at line 6)\n" +
3688+
"\tprint E.ONE.name\n" +
3689+
"\t ^^^^^^^^^^\n" +
3690+
"Groovy:[Static type checking] - No such property: name for class: E\n" +
3691+
"----------\n");
36963692
}
36973693

36983694
@Test
@@ -3711,17 +3707,13 @@ public void testCompileStatic9007or9043_enumConstToPrivate2() {
37113707
};
37123708
//@formatter:on
37133709

3714-
if (!isAtLeastGroovy(40)) {
3715-
runConformTest(sources, "", "groovy.lang.MissingPropertyException: No such property: ordinal for class: E");
3716-
} else {
3717-
runNegativeTest(sources,
3718-
"----------\n" +
3719-
"1. ERROR in Main.groovy (at line 6)\n" +
3720-
"\tprint E.ONE.ordinal\n" +
3721-
"\t ^^^^^^^^^^^^^\n" +
3722-
"Groovy:[Static type checking] - No such property: ordinal for class: E\n" +
3723-
"----------\n");
3724-
}
3710+
runNegativeTest(sources,
3711+
"----------\n" +
3712+
"1. ERROR in Main.groovy (at line 6)\n" +
3713+
"\tprint E.ONE.ordinal\n" +
3714+
"\t ^^^^^^^^^^^^^\n" +
3715+
"Groovy:[Static type checking] - No such property: ordinal for class: E\n" +
3716+
"----------\n");
37253717
}
37263718

37273719
@Test

base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java

+48-4
Original file line numberDiff line numberDiff line change
@@ -713,8 +713,15 @@ public void visitPropertyExpression(final PropertyExpression expression) {
713713

714714
if (!extension.handleUnresolvedProperty(expression)) {
715715
Expression objectExpression = expression.getObjectExpression();
716+
/* GRECLIPSE edit
716717
addStaticTypeError("No such property: " + expression.getPropertyAsString() + " for class: " +
717718
prettyPrintTypeName(findCurrentInstanceOfClass(objectExpression, getType(objectExpression))), expression);
719+
*/
720+
ClassNode objectExpressionType = (objectExpression instanceof ClassExpression
721+
? objectExpression.getType() : wrapTypeIfNecessary(getType(objectExpression)));
722+
objectExpressionType = findCurrentInstanceOfClass(objectExpression, objectExpressionType);
723+
addStaticTypeError("No such property: " + expression.getPropertyAsString() + " for class: " + prettyPrintTypeName(objectExpressionType), expression);
724+
// GRECLIPSE end
718725
}
719726
}
720727

@@ -724,8 +731,15 @@ public void visitAttributeExpression(final AttributeExpression expression) {
724731

725732
if (!extension.handleUnresolvedAttribute(expression)) {
726733
Expression objectExpression = expression.getObjectExpression();
734+
/* GRECLIPSE edit
727735
addStaticTypeError("No such attribute: " + expression.getPropertyAsString() + " for class: " +
728736
prettyPrintTypeName(findCurrentInstanceOfClass(objectExpression, getType(objectExpression))), expression);
737+
*/
738+
ClassNode objectExpressionType = (objectExpression instanceof ClassExpression
739+
? objectExpression.getType() : wrapTypeIfNecessary(getType(objectExpression)));
740+
objectExpressionType = findCurrentInstanceOfClass(objectExpression, objectExpressionType);
741+
addStaticTypeError("No such attribute: " + expression.getPropertyAsString() + " for class: " + prettyPrintTypeName(objectExpressionType), expression);
742+
// GRECLIPSE end
729743
}
730744
}
731745

@@ -1608,9 +1622,13 @@ protected boolean existsProperty(final PropertyExpression pexp, final boolean re
16081622
property = allowStaticAccessToMember(property, staticOnly);
16091623
// prefer explicit getter or setter over property if receiver is not 'this'
16101624
if (property == null || !enclosingTypes.contains(receiverType)) {
1625+
ClassNode enclosingType = enclosingTypes.iterator().next();
16111626
if (readMode) {
1612-
if (getter != null // GRECLIPSE add -- GROOVY-6277
1613-
&& hasAccessToMember(enclosingTypes.iterator().next(), getter.getDeclaringClass(), getter.getModifiers())) {
1627+
/* GRECLIPSE edit -- GROOVY-6277, GROOVY-11319
1628+
if (getter != null) {
1629+
*/
1630+
if (getter != null && hasAccessToMember(enclosingType, getter.getDeclaringClass(), getter.getModifiers())) {
1631+
// GRECLIPSE end
16141632
ClassNode returnType = inferReturnTypeGenerics(receiverType, getter, ArgumentListExpression.EMPTY_ARGUMENTS);
16151633
storeInferredTypeForPropertyExpression(pexp, returnType);
16161634
storeTargetMethod(pexp, getter);
@@ -1620,8 +1638,15 @@ && hasAccessToMember(enclosingTypes.iterator().next(), getter.getDeclaringClass(
16201638
}
16211639
return true;
16221640
}
1641+
// GRECLIPSE add
1642+
else getter = null;
1643+
// GRECLIPSE end
16231644
} else {
1645+
/* GRECLIPSE edit
16241646
if (!setters.isEmpty()) {
1647+
*/
1648+
if (setters.stream().anyMatch(setter -> hasAccessToMember(enclosingType, setter.getDeclaringClass(), setter.getModifiers()))) {
1649+
// GRECLIPSE and
16251650
if (visitor != null) {
16261651
for (MethodNode setter : setters) {
16271652
// visiting setter will not infer the property type since return type is void, so visit a dummy field instead
@@ -1641,17 +1666,24 @@ && hasAccessToMember(enclosingTypes.iterator().next(), getter.getDeclaringClass(
16411666
}
16421667
pexp.removeNodeMetaData(READONLY_PROPERTY);
16431668
return true;
1669+
/* GRECLIPSE edit
16441670
} else if (getter != null && field == null) {
1671+
*/
1672+
} else if (field == null && getter != null && hasAccessToMember(enclosingType, getter.getDeclaringClass(), getter.getModifiers())) {
1673+
// GRECLIPSE end
16451674
pexp.putNodeMetaData(READONLY_PROPERTY, Boolean.TRUE); // GROOVY-9127
16461675
}
1676+
// GRECLIPSE add
1677+
else setters.clear();
1678+
// GRECLIPSE end
16471679
}
16481680
}
16491681

16501682
if (property != null && storeProperty(property, pexp, receiverType, visitor, receiver.getData(), !readMode)) return true;
16511683

16521684
if (field != null && storeField(field, pexp, receiverType, visitor, receiver.getData(), !readMode)) return true;
16531685

1654-
foundGetterOrSetter = (foundGetterOrSetter || !setters.isEmpty() || getter != null);
1686+
foundGetterOrSetter = (foundGetterOrSetter || getter != null || !setters.isEmpty());
16551687
}
16561688

16571689
// GROOVY-5568: the property may be defined by DGM
@@ -1853,14 +1885,26 @@ private boolean isStaticInContext(final MethodNode method) {
18531885
private boolean storeField(final FieldNode field, final PropertyExpression expressionToStoreOn, final ClassNode receiver, final ClassCodeVisitorSupport visitor, final String delegationData, final boolean lhsOfAssignment) {
18541886
if (visitor != null) visitor.visitField(field);
18551887
checkOrMarkPrivateAccess(expressionToStoreOn, field, lhsOfAssignment);
1888+
/* GRECLIPSE edit -- GROOVY-11319
18561889
boolean accessible = hasAccessToMember(isSuperExpression(expressionToStoreOn.getObjectExpression()) ? typeCheckingContext.getEnclosingClassNode() : receiver, field.getDeclaringClass(), field.getModifiers());
18571890
18581891
if (expressionToStoreOn instanceof AttributeExpression) { // TODO: expand to include PropertyExpression
18591892
if (!accessible) {
18601893
addStaticTypeError("The field " + field.getDeclaringClass().getNameWithoutPackage() + "." + field.getName() + " is not accessible", expressionToStoreOn.getProperty());
18611894
}
18621895
}
1863-
1896+
*/
1897+
boolean superField = isSuperExpression(expressionToStoreOn.getObjectExpression());
1898+
boolean accessible = ( !superField && receiver.equals(field.getDeclaringClass()) ) // GROOVY-7300
1899+
|| hasAccessToMember(typeCheckingContext.getEnclosingClassNode(), field.getDeclaringClass(), field.getModifiers());
1900+
if (!accessible) {
1901+
if (expressionToStoreOn instanceof AttributeExpression) {
1902+
addStaticTypeError("Cannot access field: " + field.getName() + " of class: " + prettyPrintTypeName(field.getDeclaringClass()), expressionToStoreOn.getProperty());
1903+
} else if (field.isPrivate()) {
1904+
return false;
1905+
}
1906+
}
1907+
// GRECLIPSE end
18641908
storeWithResolve(field.getOriginType(), receiver, field.getDeclaringClass(), field.isStatic(), expressionToStoreOn);
18651909
if (delegationData != null) {
18661910
expressionToStoreOn.putNodeMetaData(IMPLICIT_RECEIVER, delegationData);

0 commit comments

Comments
 (0)