Skip to content

Commit 4dd482c

Browse files
committed
GROOVY-5193: refactor checking
1 parent e17e3be commit 4dd482c

File tree

4 files changed

+78
-69
lines changed

4 files changed

+78
-69
lines changed

src/main/java/org/codehaus/groovy/classgen/ClassCompletionVerifier.java

+19-15
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,10 @@ public void visitMethod(final MethodNode node) {
533533
inConstructor = false;
534534
inStaticConstructor = node.isStaticConstructor();
535535
checkAbstractDeclaration(node);
536-
checkRepetitiveMethod(node);
537-
checkOverloadingPrivateAndPublic(node);
536+
if (!inStaticConstructor) {
537+
checkRepetitiveMethod(node);
538+
checkOverloadingPrivateAndPublic(node);
539+
}
538540
checkMethodForIncorrectModifiers(node);
539541
checkGenericsUsage(node, node.getParameters());
540542
checkGenericsUsage(node, node.getReturnType());
@@ -586,26 +588,28 @@ private void checkMethodForWeakerAccessPrivileges(final MethodNode mn, final Cla
586588
}
587589

588590
private void checkOverloadingPrivateAndPublic(final MethodNode node) {
589-
if (node.isStaticConstructor()) return;
590-
boolean hasPrivate = node.isPrivate();
591-
boolean hasPublic = node.isPublic();
592-
for (MethodNode method : currentClass.getMethods(node.getName())) {
593-
if (method == node) continue;
594-
if (!method.getDeclaringClass().equals(node.getDeclaringClass())) continue;
595-
if (method.isPublic() || method.isProtected()) {
596-
hasPublic = true;
597-
} else {
598-
hasPrivate = true;
591+
boolean mixed = false;
592+
if (node.isPublic()) {
593+
for (MethodNode mn : currentClass.getDeclaredMethods(node.getName())) {
594+
if (mn != node && !(mn.isPublic() || mn.isProtected())) {
595+
mixed = true;
596+
break;
597+
}
598+
}
599+
} else if (node.isPrivate()) {
600+
for (MethodNode mn : currentClass.getDeclaredMethods(node.getName())) {
601+
if (mn != node && (mn.isPublic() || mn.isProtected())) {
602+
mixed = true;
603+
break;
604+
}
599605
}
600-
if (hasPrivate && hasPublic) break;
601606
}
602-
if (hasPrivate && hasPublic) {
607+
if (mixed) { // GROOVY-5193
603608
addError("Mixing private and public/protected methods of the same name causes multimethods to be disabled and is forbidden to avoid surprising behaviour. Renaming the private methods will solve the problem.", node);
604609
}
605610
}
606611

607612
private void checkRepetitiveMethod(final MethodNode node) {
608-
if (node.isStaticConstructor()) return;
609613
for (MethodNode method : currentClass.getMethods(node.getName())) {
610614
if (method == node) continue;
611615
if (!method.getDeclaringClass().equals(node.getDeclaringClass())) continue;
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package bugs
20+
21+
import org.codehaus.groovy.control.MultipleCompilationErrorsException
22+
import org.junit.jupiter.api.Test
23+
24+
import static groovy.test.GroovyAssert.shouldFail
25+
26+
final class Groovy5193 {
27+
28+
@Test
29+
void testMixingMethodsWithPrivatePublicAccessInSameClass1() {
30+
def err = shouldFail MultipleCompilationErrorsException, '''
31+
class A5193 {
32+
static main(args) {
33+
}
34+
public find(String id) {
35+
}
36+
private <T> T find(Class<T> type, String id, boolean suppressExceptions) {
37+
}
38+
}
39+
'''
40+
assert err.message.contains('Mixing private and public/protected methods of the same name causes multimethods to be disabled')
41+
}
42+
43+
@Test
44+
void testMixingMethodsWithPrivatePublicAccessInSameClass2() {
45+
def err = shouldFail MultipleCompilationErrorsException, '''
46+
class B5193 {
47+
static main(args) {
48+
}
49+
public find(String id) {
50+
}
51+
private <T> T find(Class<T> type, String id, boolean suppressExceptions = true) {
52+
}
53+
}
54+
'''
55+
assert err.message.contains('Mixing private and public/protected methods of the same name causes multimethods to be disabled')
56+
}
57+
}

src/test/groovy/bugs/Groovy5193Bug.groovy

-52
This file was deleted.

src/test/groovy/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy

+2-2
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,7 @@ final class TraitASTTransformationTest {
18111811
"""
18121812
}
18131813

1814+
// GROOVY-5193
18141815
@Test
18151816
void testMixPrivatePublicMethodsOfSameName() {
18161817
def err = shouldFail shell, '''
@@ -1822,8 +1823,7 @@ final class TraitASTTransformationTest {
18221823
class C implements T {
18231824
}
18241825
1825-
def c = new C()
1826-
assert c.foo() == 'SECRET'
1826+
assert new C().foo() == 'SECRET'
18271827
'''
18281828
assert err =~ 'Mixing private and public/protected methods of the same name causes multimethods to be disabled'
18291829
}

0 commit comments

Comments
 (0)