[
https://issues.apache.org/jira/browse/GROOVY-11980?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18077853#comment-18077853
]
ASF GitHub Bot commented on GROOVY-11980:
-----------------------------------------
Copilot commented on code in PR #2505:
URL: https://github.com/apache/groovy/pull/2505#discussion_r3177271209
##########
src/main/java/org/codehaus/groovy/transform/AutoCloneASTTransformation.java:
##########
@@ -317,10 +317,34 @@ private static void createClone(ClassNode cNode,
List<FieldNode> fieldNodes, Lis
// return _result
body.addStatement(returnS(result));
- ClassNode[] exceptions = {make(CloneNotSupportedException.class)};
+ ClassNode[] exceptions = cloneExceptionsFor(cNode);
addGeneratedMethod(cNode, "clone", ACC_PUBLIC,
GenericsUtils.nonGeneric(cNode), Parameter.EMPTY_ARRAY, exceptions, body);
}
+ /**
+ * Returns the {@code throws} clause to use for a generated {@code clone()}
+ * override. Java overrides may narrow checked exceptions but cannot add
new
+ * ones, so the nearest superclass-declared {@code clone()} dictates the
+ * shape: if it does not declare {@link CloneNotSupportedException},
neither
+ * may we (e.g. a subclass of {@link java.util.HashMap}, whose {@code
clone()}
+ * is silenced). Defaults to {@code throws CloneNotSupportedException} when
+ * no narrowing parent intervenes, matching {@link Object#clone()}.
+ */
+ static ClassNode[] cloneExceptionsFor(ClassNode cNode) {
+ for (ClassNode sc = cNode.getSuperClass(); sc != null &&
!isObjectType(sc); sc = sc.getSuperClass()) {
+ MethodNode parent = sc.getDeclaredMethod("clone",
Parameter.EMPTY_ARRAY);
+ if (parent != null) {
+ for (ClassNode ex : parent.getExceptions()) {
+ if
("java.lang.CloneNotSupportedException".equals(ex.getName())) {
+ return new
ClassNode[]{make(CloneNotSupportedException.class)};
+ }
+ }
+ return ClassNode.EMPTY_ARRAY;
Review Comment:
`cloneExceptionsFor` stops at the first superclass that declares `clone()`,
even if that method is `private` (or package-private from another package).
Those methods are not inherited, so they do not constrain the checked
exceptions of this override. In that case we should keep walking to the next
visible superclass method (or `Object.clone()`), otherwise `@AutoClone` can
incorrectly strip `CloneNotSupportedException` from subclasses whose nearest
declared `clone()` is non-overridable.
##########
src/main/java/org/codehaus/groovy/transform/AutoCloneASTTransformation.java:
##########
@@ -317,10 +317,34 @@ private static void createClone(ClassNode cNode,
List<FieldNode> fieldNodes, Lis
// return _result
body.addStatement(returnS(result));
- ClassNode[] exceptions = {make(CloneNotSupportedException.class)};
+ ClassNode[] exceptions = cloneExceptionsFor(cNode);
addGeneratedMethod(cNode, "clone", ACC_PUBLIC,
GenericsUtils.nonGeneric(cNode), Parameter.EMPTY_ARRAY, exceptions, body);
}
+ /**
+ * Returns the {@code throws} clause to use for a generated {@code clone()}
+ * override. Java overrides may narrow checked exceptions but cannot add
new
+ * ones, so the nearest superclass-declared {@code clone()} dictates the
+ * shape: if it does not declare {@link CloneNotSupportedException},
neither
+ * may we (e.g. a subclass of {@link java.util.HashMap}, whose {@code
clone()}
+ * is silenced). Defaults to {@code throws CloneNotSupportedException} when
+ * no narrowing parent intervenes, matching {@link Object#clone()}.
+ */
+ static ClassNode[] cloneExceptionsFor(ClassNode cNode) {
Review Comment:
This PR adds a new code path for classes whose superclass narrows away
`CloneNotSupportedException` (the `HashMap` case from GROOVY-11980), but there
isn't a regression test covering that path. The existing `@AutoClone` tests
only exercise the default `throws CloneNotSupportedException` signature, so a
future change could easily break the new runtime/stub behavior without being
caught.
> @AutoClone clone() override adds CloneNotSupportedException not declared by
> superclass
> --------------------------------------------------------------------------------------
>
> Key: GROOVY-11980
> URL: https://issues.apache.org/jira/browse/GROOVY-11980
> Project: Groovy
> Issue Type: Bug
> Reporter: Paul King
> Assignee: Paul King
> Priority: Major
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)