Skip to content

Commit

Permalink
GROOVY-11319
Browse files Browse the repository at this point in the history
  • Loading branch information
eric-milles committed Apr 6, 2024
1 parent 0e247a8 commit 2927b89
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3682,17 +3682,13 @@ public void testCompileStatic9007or9043_enumConstToPrivate1() {
};
//@formatter:on

if (!isAtLeastGroovy(40)) {
runConformTest(sources, "", "groovy.lang.MissingPropertyException: No such property: name for class: E");
} else {
runNegativeTest(sources,
"----------\n" +
"1. ERROR in Main.groovy (at line 6)\n" +
"\tprint E.ONE.name\n" +
"\t ^^^^^^^^^^\n" +
"Groovy:[Static type checking] - No such property: name for class: E\n" +
"----------\n");
}
runNegativeTest(sources,
"----------\n" +
"1. ERROR in Main.groovy (at line 6)\n" +
"\tprint E.ONE.name\n" +
"\t ^^^^^^^^^^\n" +
"Groovy:[Static type checking] - No such property: name for class: E\n" +
"----------\n");
}

@Test
Expand All @@ -3711,17 +3707,13 @@ public void testCompileStatic9007or9043_enumConstToPrivate2() {
};
//@formatter:on

if (!isAtLeastGroovy(40)) {
runConformTest(sources, "", "groovy.lang.MissingPropertyException: No such property: ordinal for class: E");
} else {
runNegativeTest(sources,
"----------\n" +
"1. ERROR in Main.groovy (at line 6)\n" +
"\tprint E.ONE.ordinal\n" +
"\t ^^^^^^^^^^^^^\n" +
"Groovy:[Static type checking] - No such property: ordinal for class: E\n" +
"----------\n");
}
runNegativeTest(sources,
"----------\n" +
"1. ERROR in Main.groovy (at line 6)\n" +
"\tprint E.ONE.ordinal\n" +
"\t ^^^^^^^^^^^^^\n" +
"Groovy:[Static type checking] - No such property: ordinal for class: E\n" +
"----------\n");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,15 @@ public void visitPropertyExpression(final PropertyExpression expression) {

if (!extension.handleUnresolvedProperty(expression)) {
Expression objectExpression = expression.getObjectExpression();
/* GRECLIPSE edit
addStaticTypeError("No such property: " + expression.getPropertyAsString() + " for class: " +
prettyPrintTypeName(findCurrentInstanceOfClass(objectExpression, getType(objectExpression))), expression);
*/
ClassNode objectExpressionType = (objectExpression instanceof ClassExpression
? objectExpression.getType() : wrapTypeIfNecessary(getType(objectExpression)));
objectExpressionType = findCurrentInstanceOfClass(objectExpression, objectExpressionType);
addStaticTypeError("No such property: " + expression.getPropertyAsString() + " for class: " + prettyPrintTypeName(objectExpressionType), expression);
// GRECLIPSE end
}
}

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

if (!extension.handleUnresolvedAttribute(expression)) {
Expression objectExpression = expression.getObjectExpression();
/* GRECLIPSE edit
addStaticTypeError("No such attribute: " + expression.getPropertyAsString() + " for class: " +
prettyPrintTypeName(findCurrentInstanceOfClass(objectExpression, getType(objectExpression))), expression);
*/
ClassNode objectExpressionType = (objectExpression instanceof ClassExpression
? objectExpression.getType() : wrapTypeIfNecessary(getType(objectExpression)));
objectExpressionType = findCurrentInstanceOfClass(objectExpression, objectExpressionType);
addStaticTypeError("No such attribute: " + expression.getPropertyAsString() + " for class: " + prettyPrintTypeName(objectExpressionType), expression);
// GRECLIPSE end
}
}

Expand Down Expand Up @@ -1608,9 +1622,13 @@ protected boolean existsProperty(final PropertyExpression pexp, final boolean re
property = allowStaticAccessToMember(property, staticOnly);
// prefer explicit getter or setter over property if receiver is not 'this'
if (property == null || !enclosingTypes.contains(receiverType)) {
ClassNode enclosingType = enclosingTypes.iterator().next();
if (readMode) {
if (getter != null // GRECLIPSE add -- GROOVY-6277
&& hasAccessToMember(enclosingTypes.iterator().next(), getter.getDeclaringClass(), getter.getModifiers())) {
/* GRECLIPSE edit -- GROOVY-6277, GROOVY-11319
if (getter != null) {
*/
if (getter != null && hasAccessToMember(enclosingType, getter.getDeclaringClass(), getter.getModifiers())) {
// GRECLIPSE end
ClassNode returnType = inferReturnTypeGenerics(receiverType, getter, ArgumentListExpression.EMPTY_ARGUMENTS);
storeInferredTypeForPropertyExpression(pexp, returnType);
storeTargetMethod(pexp, getter);
Expand All @@ -1620,8 +1638,15 @@ && hasAccessToMember(enclosingTypes.iterator().next(), getter.getDeclaringClass(
}
return true;
}
// GRECLIPSE add
else getter = null;
// GRECLIPSE end
} else {
/* GRECLIPSE edit
if (!setters.isEmpty()) {
*/
if (setters.stream().anyMatch(setter -> hasAccessToMember(enclosingType, setter.getDeclaringClass(), setter.getModifiers()))) {
// GRECLIPSE and
if (visitor != null) {
for (MethodNode setter : setters) {
// visiting setter will not infer the property type since return type is void, so visit a dummy field instead
Expand All @@ -1641,17 +1666,24 @@ && hasAccessToMember(enclosingTypes.iterator().next(), getter.getDeclaringClass(
}
pexp.removeNodeMetaData(READONLY_PROPERTY);
return true;
/* GRECLIPSE edit
} else if (getter != null && field == null) {
*/
} else if (field == null && getter != null && hasAccessToMember(enclosingType, getter.getDeclaringClass(), getter.getModifiers())) {
// GRECLIPSE end
pexp.putNodeMetaData(READONLY_PROPERTY, Boolean.TRUE); // GROOVY-9127
}
// GRECLIPSE add
else setters.clear();
// GRECLIPSE end
}
}

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

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
Expand Down Expand Up @@ -1853,14 +1885,26 @@ private boolean isStaticInContext(final MethodNode method) {
private boolean storeField(final FieldNode field, final PropertyExpression expressionToStoreOn, final ClassNode receiver, final ClassCodeVisitorSupport visitor, final String delegationData, final boolean lhsOfAssignment) {
if (visitor != null) visitor.visitField(field);
checkOrMarkPrivateAccess(expressionToStoreOn, field, lhsOfAssignment);
/* GRECLIPSE edit -- GROOVY-11319
boolean accessible = hasAccessToMember(isSuperExpression(expressionToStoreOn.getObjectExpression()) ? typeCheckingContext.getEnclosingClassNode() : receiver, field.getDeclaringClass(), field.getModifiers());
if (expressionToStoreOn instanceof AttributeExpression) { // TODO: expand to include PropertyExpression
if (!accessible) {
addStaticTypeError("The field " + field.getDeclaringClass().getNameWithoutPackage() + "." + field.getName() + " is not accessible", expressionToStoreOn.getProperty());
}
}

*/
boolean superField = isSuperExpression(expressionToStoreOn.getObjectExpression());
boolean accessible = ( !superField && receiver.equals(field.getDeclaringClass()) ) // GROOVY-7300
|| hasAccessToMember(typeCheckingContext.getEnclosingClassNode(), field.getDeclaringClass(), field.getModifiers());
if (!accessible) {
if (expressionToStoreOn instanceof AttributeExpression) {
addStaticTypeError("Cannot access field: " + field.getName() + " of class: " + prettyPrintTypeName(field.getDeclaringClass()), expressionToStoreOn.getProperty());
} else if (field.isPrivate()) {
return false;
}
}
// GRECLIPSE end
storeWithResolve(field.getOriginType(), receiver, field.getDeclaringClass(), field.isStatic(), expressionToStoreOn);
if (delegationData != null) {
expressionToStoreOn.putNodeMetaData(IMPLICIT_RECEIVER, delegationData);
Expand Down

0 comments on commit 2927b89

Please sign in to comment.