8174840: Elements.overrides does not check the return type of the methods

Co-authored-by: Pavel Rappo <prappo@openjdk.org>
Reviewed-by: liach, darcy
This commit is contained in:
Nizar Benalla 2025-05-05 21:52:25 +00:00
parent 2a4f37cc16
commit 606f2012b0
3 changed files with 134 additions and 1 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -778,6 +778,12 @@ public interface Elements {
* elements.getTypeElement("I"));
* }
*
* @apiNote This method examines the method's name, signature, subclass relationship, and accessibility
* in determining whether one method overrides another, as specified in JLS {@jls 8.4.8.1}.
* In addition, an implementation may have stricter checks including method modifiers, return types and
* exception types as described in JLS {@jls 8.4.8.1} and {@jls 8.4.8.3}.
* Note that such additional compile-time checks are not guaranteed and may vary between implementations.
*
* @param overrider the first method, possible overrider
* @param overridden the second method, possibly being overridden
* @param type the class or interface of which the first method is a member

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file models a few cases where Elements.overrides produces a false
* positive which warrants @apiNote.
*/
// S.java does not compile because it violates the JLS rules for overrides
class S {
public void m() { }
}
// `protected` is a weaker modifier than `public`
class T1 extends S {
protected void m() { }
}
// `package-private` is a weaker modifier than `public`
class T2 extends S {
void m() { }
}
// `private` methods cannot override public method
class T3 extends S {
private void m() { }
}
// return type int is not compatible with void
class T4 extends S {
public int m() { return 0; }
}
// adding a checked exception violates the override rule
class T5 extends S {
public void m() throws Exception { }
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8174840
* @library /tools/javac/lib
* @build JavacTestingAbstractProcessor TestOverrides
* @compile -processor TestOverrides -proc:only S.java
*/
import java.util.Set;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import static javax.lang.model.element.ElementKind.METHOD;
public class TestOverrides extends JavacTestingAbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment round) {
if (!round.processingOver()) {
var sm = mIn(elements.getTypeElement("S"));
for (var subtypeName : new String[]{"T1", "T2", "T3", "T4", "T5"}) {
var t = elements.getTypeElement(subtypeName);
var tm = mIn(t);
if (!elements.overrides(tm, sm, t))
messager.printError(String.format(
"%s does not override from %s method %s", tm, t.getQualifiedName(), sm));
}
}
return true;
}
private ExecutableElement mIn(TypeElement t) {
return t.getEnclosedElements().stream()
.filter(e -> e.getKind() == METHOD)
.filter(e -> e.getSimpleName().toString().equals("m"))
.map(e -> (ExecutableElement) e)
.findAny()
.get();
}
}