Skip to content

Commit 606f201

Browse files
8174840: Elements.overrides does not check the return type of the methods
Co-authored-by: Pavel Rappo <[email protected]> Reviewed-by: liach, darcy
1 parent 2a4f37c commit 606f201

File tree

3 files changed

+134
-1
lines changed

3 files changed

+134
-1
lines changed

src/java.compiler/share/classes/javax/lang/model/util/Elements.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -778,6 +778,12 @@ default TypeElement getOutermostTypeElement(Element e) {
778778
* elements.getTypeElement("I"));
779779
* }
780780
*
781+
* @apiNote This method examines the method's name, signature, subclass relationship, and accessibility
782+
* in determining whether one method overrides another, as specified in JLS {@jls 8.4.8.1}.
783+
* In addition, an implementation may have stricter checks including method modifiers, return types and
784+
* exception types as described in JLS {@jls 8.4.8.1} and {@jls 8.4.8.3}.
785+
* Note that such additional compile-time checks are not guaranteed and may vary between implementations.
786+
*
781787
* @param overrider the first method, possible overrider
782788
* @param overridden the second method, possibly being overridden
783789
* @param type the class or interface of which the first method is a member
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* This file models a few cases where Elements.overrides produces a false
26+
* positive which warrants @apiNote.
27+
*/
28+
29+
// S.java does not compile because it violates the JLS rules for overrides
30+
class S {
31+
32+
public void m() { }
33+
}
34+
35+
// `protected` is a weaker modifier than `public`
36+
class T1 extends S {
37+
38+
protected void m() { }
39+
}
40+
41+
// `package-private` is a weaker modifier than `public`
42+
class T2 extends S {
43+
44+
void m() { }
45+
}
46+
47+
// `private` methods cannot override public method
48+
class T3 extends S {
49+
50+
private void m() { }
51+
}
52+
53+
// return type int is not compatible with void
54+
class T4 extends S {
55+
56+
public int m() { return 0; }
57+
}
58+
59+
// adding a checked exception violates the override rule
60+
class T5 extends S {
61+
62+
public void m() throws Exception { }
63+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8174840
27+
* @library /tools/javac/lib
28+
* @build JavacTestingAbstractProcessor TestOverrides
29+
* @compile -processor TestOverrides -proc:only S.java
30+
*/
31+
32+
import java.util.Set;
33+
import javax.annotation.processing.RoundEnvironment;
34+
import javax.lang.model.element.ExecutableElement;
35+
import javax.lang.model.element.TypeElement;
36+
37+
import static javax.lang.model.element.ElementKind.METHOD;
38+
39+
public class TestOverrides extends JavacTestingAbstractProcessor {
40+
41+
@Override
42+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment round) {
43+
if (!round.processingOver()) {
44+
var sm = mIn(elements.getTypeElement("S"));
45+
for (var subtypeName : new String[]{"T1", "T2", "T3", "T4", "T5"}) {
46+
var t = elements.getTypeElement(subtypeName);
47+
var tm = mIn(t);
48+
if (!elements.overrides(tm, sm, t))
49+
messager.printError(String.format(
50+
"%s does not override from %s method %s", tm, t.getQualifiedName(), sm));
51+
}
52+
}
53+
return true;
54+
}
55+
56+
private ExecutableElement mIn(TypeElement t) {
57+
return t.getEnclosedElements().stream()
58+
.filter(e -> e.getKind() == METHOD)
59+
.filter(e -> e.getSimpleName().toString().equals("m"))
60+
.map(e -> (ExecutableElement) e)
61+
.findAny()
62+
.get();
63+
}
64+
}

0 commit comments

Comments
 (0)