This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
new 3c96c6f6bb GROOVY-10897: STC: remove interface equivalent for indirect
interface
3c96c6f6bb is described below
commit 3c96c6f6bb9f94592d34d88f58d0df20c6c6a1ce
Author: Eric Milles <[email protected]>
AuthorDate: Fri Dec 8 14:50:00 2023 -0600
GROOVY-10897: STC: remove interface equivalent for indirect interface
```
A
/ \
B C
\ /
D
```
`A` and `B` are interfaces; `C` and `D` are concrete classes
`B` and `C` both provide method `m()` then drop `B#m()` as equivalent
---
.../transform/stc/StaticTypeCheckingSupport.java | 3 +-
.../groovy/transform/stc/MethodCallsSTCTest.groovy | 296 +++++++++++++++++++++
.../asm/sc/MethodCallsStaticCompilationTest.groovy | 268 ++-----------------
3 files changed, 315 insertions(+), 252 deletions(-)
diff --git
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index ea94d53145..2235ec63de 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1209,7 +1209,8 @@ public abstract class StaticTypeCheckingSupport {
} else if (!oneDC.equals(twoDC)) {
if
(ParameterUtils.parametersEqual(one.getParameters(), two.getParameters())) {
// GROOVY-6882, GROOVY-6970: drop overridden or
interface equivalent method
- if (twoDC.isInterface() ?
oneDC.implementsInterface(twoDC) : oneDC.isDerivedFrom(twoDC)) {
+ if (!twoDC.isInterface() ?
oneDC.isDerivedFrom(twoDC) : oneDC.implementsInterface(twoDC) || //
GROOVY-10897: concrete vs. abstract
+
(!one.isAbstract() && !(two instanceof
ExtensionMethodNode))) {
toBeRemoved.add(two);
} else if (oneDC.isInterface() ?
twoDC.isInterface() : twoDC.isDerivedFrom(oneDC)) {
toBeRemoved.add(one);
diff --git a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
index c07168394b..6907fe9afd 100644
--- a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -18,6 +18,8 @@
*/
package groovy.transform.stc
+import org.codehaus.groovy.control.MultipleCompilationErrorsException
+
import static
org.codehaus.groovy.control.customizers.builder.CompilerCustomizationBuilder.withConfig
/**
@@ -148,6 +150,22 @@ class MethodCallsSTCTest extends
StaticTypeCheckingTestCase {
'''
}
+ void testPlusStaticMethodCall() {
+ assertScript '''
+ static int foo() { 1 }
+ assert 1+foo() == 2
+ '''
+ }
+
+ void testExplicitTargetMethodWithCast() {
+ assertScript '''
+ String foo(String str) { 'STRING' }
+ String foo(Object o) { 'OBJECT' }
+ assert foo('call') == 'STRING'
+ assert foo((Object)'call') == 'OBJECT'
+ '''
+ }
+
void testGenericMethodCall() {
assertScript '''
C c = new C()
@@ -237,6 +255,99 @@ class MethodCallsSTCTest extends
StaticTypeCheckingTestCase {
'''
}
+ void testNullSafeCall() {
+ assertScript '''
+ String str = null
+ assert str?.toString() == null
+ '''
+ }
+
+ void testCallToSuper() {
+ assertScript '''
+ class Foo {
+ int foo() { 1 }
+ }
+ class Bar extends Foo {
+ int foo() { super.foo() }
+ }
+ def bar = new Bar()
+ assert bar.foo() == 1
+ '''
+ }
+
+ // GROOVY-10897
+ void testCallToSuper2() {
+ assertScript '''
+ interface A10897 {
+ def m()
+ }
+ interface B10897 extends A10897 {
+ @Override def m()
+ }
+ class C10897 implements A10897 {
+ @Override def m() { "C" }
+ }
+ class D10897 extends C10897 implements B10897 {
+ }
+ class E10897 extends D10897 {
+ @Override
+ def m() {
+ "E then " + super.m()
+ }
+ }
+ assert new E10897().m() == 'E then C'
+ '''
+ }
+
+ // GROOVY-11242
+ void testCallToSuper3() {
+ assertScript '''
+ class DirtyCheckingCollection implements Collection {
+ private final @Delegate Collection target
+ DirtyCheckingCollection(Collection target) {
+ this.target = target
+ }
+ @Override
+ boolean add(Object o) {
+ target.add(o)
+ }
+ }
+ class DirtyCheckingSet extends DirtyCheckingCollection implements
Set {
+ DirtyCheckingSet(Set target) {
+ super(target)
+ }
+ }
+ class MySet extends DirtyCheckingSet {
+ MySet(Set delegate) {
+ super(delegate)
+ }
+ @Override
+ boolean add(Object o) {
+ super.add(o) // StackOverflowError
+ }
+ }
+ MySet set = new MySet([] as Set)
+ set.add('myProperty')
+ '''
+ }
+
+ void testCallToSuperDefault() {
+ assertScript '''
+ interface I<T> {
+ default m(T t) {
+ return t
+ }
+ }
+ class C implements I<String> {
+ @Override m(String s) {
+ I.super.m(s)
+ }
+ }
+ String result = new C().m('works')
+ assert result == 'works'
+ '''
+ }
+
// GROOVY-10922
void testCallToSuperGenerated() {
assertScript '''
@@ -276,6 +387,152 @@ class MethodCallsSTCTest extends
StaticTypeCheckingTestCase {
'''
}
+ void testCallToPrivateInnerClassMethod() {
+ assertScript '''
+ class Outer {
+ static class Inner {
+ private static void foo() {}
+ }
+ static main(args) { Inner.foo() }
+ }
+ '''
+ }
+
+ void testCallToPrivateOuterClassMethod() {
+ assertScript '''
+ class Outer {
+ private static void foo() {}
+ static class Inner {
+ private static void bar() { Outer.foo() }
+ }
+ }
+ new Outer.Inner()
+ '''
+ }
+
+ void testCallToPrivateInnerClassConstant() {
+ assertScript '''
+ class Outer {
+ static class Inner {
+ private static int foo = 42
+ }
+ static main(args) { Inner.foo }
+ }
+ '''
+ }
+
+ void testCallToPrivateOuterClassConstant() {
+ assertScript '''
+ class Outer {
+ private static int foo = 42
+ static class Inner {
+ private static void bar() { Outer.foo }
+ }
+ }
+ new Outer.Inner()
+ '''
+ }
+
+ void testReferenceToInaccessiblePrivateMethod() {
+ shouldFail(MultipleCompilationErrorsException) {
+ assertScript '''
+ class Main {
+ static main(args) { Peer.foo() }
+ }
+ class Peer {
+ private static void foo() {}
+ }
+ '''
+ }
+ }
+
+ // GROOVY-6647
+ void testReferenceToInaccessiblePrivateConstructor() {
+ shouldFailWithMessages '''
+ class Main {
+ private Main() {}
+ }
+ class Peer {
+ def foo() { new Main() }
+ }
+ ''',
+ 'Cannot find matching method Main#<init>()'
+ }
+
+ // GROOVY-8509
+ void testCallProtectedFromClassInSamePackage() {
+ assertScript '''
+ class Foo {
+ protected Foo() {}
+ protected int m() { 123 }
+ }
+ class Bar {
+ int test() {
+ new Foo().m()
+ }
+ }
+ assert new Bar().test() == 123
+ '''
+ }
+
+ // GROOVY-7862
+ void testCallProtectedMethodFromInnerClassInSeparatePackage() {
+ assertScript '''
+ import groovy.transform.stc.MethodCallsSTCTest.BaseWithProtected
as Foo
+
+ class Bar extends Foo {
+ class Baz {
+ int test() {
+ m()
+ }
+ }
+ int test() {
+ new Baz().test()
+ }
+ }
+ assert new Bar().test() == 1
+ '''
+ }
+
+ // GROOVY-7063
+ void testCallProtectedMethodFromSubclassClosureInDifferentPackage() {
+ assertScript '''
+ import groovy.transform.stc.MethodCallsSTCTest.BaseWithProtected
as Foo
+
+ class Bar extends Foo {
+ int baz() {
+ def c = {
+ m()
+ }
+ c.call()
+ }
+ }
+ def bar = new Bar()
+ assert bar.baz() == 1
+ '''
+ }
+
+ // GROOVY-7264
+ void testCallProtectedMethodWithGenericTypes() {
+ assertScript '''
+ class Foo<T> {
+ protected boolean m(T t) {
+ true
+ }
+ }
+ class Bar extends Foo<Integer> {
+ int baz() {
+ def c = {
+ m(123)
+ }
+ c.call() ? 1 : 0
+ }
+ }
+ def bar = new Bar()
+ assert bar.baz() == 1
+ '''
+ }
+
// GROOVY-5175
void testCallMethodAcceptingArrayWithNull() {
assertClass '''
@@ -346,6 +603,17 @@ class MethodCallsSTCTest extends
StaticTypeCheckingTestCase {
'''
}
+ void testMethodCallWithDefaultParams() {
+ assertScript '''
+ class Support {
+ Support(String name, String val, List arg=null, Set set =
null, Date suffix = new Date()) {
+ "$name$val$suffix"
+ }
+ }
+ new Support(null, null, null, null)
+ '''
+ }
+
void testMethodCallArgumentUsingInstanceOf() {
assertScript '''
void foo(String str) { 'String' }
@@ -490,6 +758,34 @@ class MethodCallsSTCTest extends
StaticTypeCheckingTestCase {
'Reference to method is ambiguous'
}
+ // GROOVY-5703
+ void testShouldNotConvertStringToStringArray() {
+ assertScript '''
+ int printMsgs(String ... msgs) {
+ int i = 0
+ for(String s : msgs) { i++ }
+
+ i
+ }
+ assert printMsgs('foo') == 1
+ assert printMsgs('foo','bar') == 2
+ '''
+ }
+
+ // GROOVY-5780
+ void testShouldNotConvertGStringToStringArray() {
+ assertScript '''
+ int printMsgs(String ... msgs) {
+ int i = 0
+ for(String s : msgs) { i++ }
+
+ i
+ }
+ assert printMsgs("f${'o'}o") == 1
+ assert printMsgs("${'foo'}","${'bar'}") == 2
+ '''
+ }
+
void testInstanceOfOnExplicitParameter() {
assertScript '''
1.with { obj ->
diff --git
a/src/test/org/codehaus/groovy/classgen/asm/sc/MethodCallsStaticCompilationTest.groovy
b/src/test/org/codehaus/groovy/classgen/asm/sc/MethodCallsStaticCompilationTest.groovy
index 40d6cd0040..e80c6586e3 100644
---
a/src/test/org/codehaus/groovy/classgen/asm/sc/MethodCallsStaticCompilationTest.groovy
+++
b/src/test/org/codehaus/groovy/classgen/asm/sc/MethodCallsStaticCompilationTest.groovy
@@ -23,269 +23,35 @@ import
org.codehaus.groovy.control.MultipleCompilationErrorsException
public class MethodCallsStaticCompilationTest extends MethodCallsSTCTest
implements StaticCompilationTestSupport {
- void testCallToSuper() {
- assertScript '''
- class Foo {
- int foo() { 1 }
- }
- class Bar extends Foo {
- int foo() { super.foo() }
- }
- def bar = new Bar()
- assert bar.foo() == 1
- '''
- }
-
- void testNullSafeCall() {
- assertScript '''
- String str = null
- assert str?.toString() == null
- '''
- }
-
- void testCallToPrivateInnerClassMethod() {
- assertScript '''
- class A {
- static class B { private static void foo() {} }
- public static void main(args) { B.foo() }
- }
- '''
- }
-
- void testCallToPrivateOuterClassMethod() {
- assertScript '''
- class A {
- private static void foo() {}
- static class B { private static void bar() { A.foo() } }
- }
- new A.B()
- '''
- }
-
- void testCallToPrivateInnerClassConstant() {
- assertScript '''
- class A {
- static class B { private static int foo = 333 }
- public static void main(args) { B.foo }
- }
- '''
- }
-
- void testCallToPrivateOuterClassConstant() {
- assertScript '''
- class A {
- private static int foo = 333
- static class B { private static void bar() { A.foo } }
- }
- new A.B()
- '''
- }
-
- void testForbiddenCallToPrivateMethod() {
+ void testReferenceToInaccessiblePrivateProperty() {
shouldFail(MultipleCompilationErrorsException) {
assertScript '''
- class A {
- public static void main(args) { B.foo() }
- }
- class B { private static void foo() {} }
- '''
- }
- }
-
- void testForbiddenCallToPrivateConstant() {
- shouldFail(MultipleCompilationErrorsException) {
- assertScript '''
- class A {
- public static void main(args) { B.foo }
- }
- class B { private static int foo = 666 }
- '''
- }
- }
-
- void testExplicitTargetMethodWithCast() {
- assertScript '''
- String foo(String str) { 'STRING' }
- String foo(Object o) { 'OBJECT' }
- assert foo('call') == 'STRING'
- assert foo((Object)'call') == 'OBJECT'
- '''
- }
-
- void testPlusStaticMethodCall() {
- assertScript '''
- static int foo() { 1 }
- assert 1+foo() == 2
- '''
- }
-
- // GROOVY-5703
- void testShouldNotConvertStringToStringArray() {
- assertScript '''
- int printMsgs(String ... msgs) {
- int i = 0
- for(String s : msgs) { i++ }
-
- i
- }
- assert printMsgs('foo') == 1
- assert printMsgs('foo','bar') == 2
- '''
- }
-
- // GROOVY-5780
- void testShouldNotConvertGStringToStringArray() {
- assertScript '''
- int printMsgs(String ... msgs) {
- int i = 0
- for(String s : msgs) { i++ }
-
- i
- }
- assert printMsgs("f${'o'}o") == 1
- assert printMsgs("${'foo'}","${'bar'}") == 2
- '''
- }
-
- void testMethodCallWithDefaultParams() {
- assertScript '''import groovy.transform.CompileStatic
-import groovy.transform.TypeCheckingMode//import
org.codehaus.groovy.classgen.asm.sc.MethodCallsStaticCompilationTest.DefaultParamTestSupport
as Support
-@CompileStatic(TypeCheckingMode.SKIP)
- class Support {
- Support(String name, String val, List arg=null, Set set = null, Date
suffix = new Date()) {
- "$name$val$suffix"
- }
- }
- new Support(null, null, null, null)
-
- '''
- }
-
- static class DefaultParamTestSupport {
- DefaultParamTestSupport(String name, String val, List arg=null, Set
set = null, Date suffix = new Date()) {
- "$name$val$suffix"
- }
- }
-
- // GROOVY-6647
- void testInaccessibleConstructor() {
- shouldFailWithMessages '''
- class Foo {
- private Foo(){}
- }
-
- class Bar {
- def foo() {new Foo()}
- }
- ''', '[Static type checking] - Cannot find matching method
Foo#<init>()'
- }
-
- // GROOVY-7063
- void testCallToProtectedMethodFromClosureInSubclassAndDifferentPackage() {
- assertScript ''' import
org.codehaus.groovy.classgen.asm.sc.MethodCallsStaticCompilationTest.Base
-
- class Ext extends Base {
-
- int doSomething() {
- def c = {
- foo()
+ class Main {
+ static main(args) { Peer.xxx }
}
- c.call()
- }
- }
- def ext = new Ext()
- assert ext.doSomething() == 123
- '''
- }
-
- // GROOVY-7264
- void testCallProtectedMethodWithGenericTypes() {
- assertScript '''
- import
org.codehaus.groovy.classgen.asm.sc.MethodCallsStaticCompilationTest.BaseGeneric
-
- class Ext extends BaseGeneric<Integer> {
-
- int doSomething() {
- def c = {
- foo(123)
- }
- c.call()?1:0
+ class Peer {
+ private static int xxx = 666
}
- }
- def ext = new Ext()
- assert ext.doSomething() == 1
- '''
+ '''
+ }
}
- //GROOVY-7863
+ // GROOVY-7863
void testDoublyNestedPrivateMethodAccess() {
assertScript '''
- class A {
- private int bar() { 123 }
-
- class B {
-
- int testInner() { new C().barInner() }
-
- class C {
- int barInner() { bar() }
- }
- }
-
- int test() {
- new B().testInner()
- }
- }
- assert new A().test() == 123
- '''
- }
-
- //GROOVY-7862
- void testProtectedCallFromInnerClassInSeparatePackage() {
- assertScript '''
- import
org.codehaus.groovy.classgen.asm.sc.MethodCallsStaticCompilationTest.Base
- class SubBase extends Base {
- class Inner {
- int test() {
- foo()
+ class Foo {
+ class Bar {
+ class Baz {
+ int c() { d() }
}
+ int b() { new Baz().c() }
}
-
- int innerTest() {
- new Inner().test()
+ int a() {
+ new Bar().b()
}
+ private int d() { 123 }
}
- assert new SubBase().innerTest() == 123
+ assert new Foo().a() == 123
'''
}
-
- //GROOVY-8509
- void testProtectedCallFromClassInSamePackage() {
- assertScript '''
- package org.foo
-
- class A {
- protected A() {}
- protected int m() { 123 }
- }
- class B {
- int test() {
- new A().m()
- }
- }
- assert new B().test() == 123
- '''
- }
-
- public static class Base {
- protected int foo() {
- 123
- }
- }
-
- public static class BaseGeneric<T> {
- protected boolean foo(T t) {
- true
- }
- }
}