You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/11/23 16:14:48 UTC
[groovy] 01/02: GROOVY-10820: STC: static methods for `Type.name()` except from `Class`
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit eeec29e6e89a2ee2a1655717494abffb6c87135d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 10 14:56:31 2022 -0600
GROOVY-10820: STC: static methods for `Type.name()` except from `Class`
---
.../transform/stc/StaticTypeCheckingVisitor.java | 86 +--
src/spec/test/typing/TypeCheckingTest.groovy | 3 +-
src/test/groovy/bugs/Groovy7204.groovy | 4 +-
src/test/groovy/bugs/Groovy7987.groovy | 44 --
src/test/groovy/bugs/Groovy8609Bug.groovy | 171 +++--
.../groovy/transform/stc/GenericsSTCTest.groovy | 20 +-
.../groovy/transform/stc/MethodCallsSTCTest.groovy | 129 ++--
.../classgen/asm/sc/BugsStaticCompileTest.groovy | 689 +++++++++++----------
.../asm/sc/StaticCompilationTestSupport.groovy | 2 +
.../main/groovy/groovy/console/ui/Console.groovy | 24 +-
10 files changed, 568 insertions(+), 604 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index b0f18982a0..7e53d497e3 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1803,10 +1803,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
boolean isStatic;
if (member instanceof FieldNode) {
isStatic = ((FieldNode) member).isStatic();
- } else if (member instanceof MethodNode) {
- isStatic = ((MethodNode) member).isStatic();
- } else {
+ } else if (member instanceof PropertyNode) {
isStatic = ((PropertyNode) member).isStatic();
+ } else { // assume member instanceof MethodNode
+ isStatic = member instanceof ExtensionMethodNode ? ((ExtensionMethodNode) member).isStaticExtension() : ((MethodNode) member).isStatic();
}
return (isStatic ? member : null);
}
@@ -3324,7 +3324,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (dmd.getParent() == null) {
receivers.addAll(owners);
} else {
- //receivers.add(new Receiver<String>(CLOSURE_TYPE, path + "owner"));
+ //receivers.add(new Receiver<String>(CLOSURE_TYPE, path + "owner"));
addReceivers(receivers, owners, dmd.getParent(), path + "owner.");
}
}
@@ -3334,7 +3334,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (dmd.getParent() == null) {
receivers.addAll(owners);
} else {
- //receivers.add(new Receiver<String>(CLOSURE_TYPE, path + "owner"));
+ //receivers.add(new Receiver<String>(CLOSURE_TYPE, path + "owner"));
addReceivers(receivers, owners, dmd.getParent(), path + "owner.");
}
if (strategy == Closure.OWNER_FIRST) {
@@ -3345,6 +3345,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
private static void addDelegateReceiver(final List<Receiver<String>> receivers, final ClassNode delegate, final String path) {
+ if (isClassClassNodeWrappingConcreteType(delegate)) { // add Type from Class<Type>
+ addDelegateReceiver(receivers, delegate.getGenericsTypes()[0].getType(), path);
+ }
if (receivers.stream().map(Receiver::getType).noneMatch(delegate::equals)) {
receivers.add(new Receiver<>(delegate, path));
}
@@ -3477,38 +3480,20 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
List<Receiver<String>> receivers = new ArrayList<>();
addReceivers(receivers, makeOwnerList(objectExpression), call.isImplicitThis());
+ MethodNode first = null;
List<MethodNode> mn = null;
Receiver<String> chosenReceiver = null;
for (Receiver<String> currentReceiver : receivers) {
- ClassNode receiverType = currentReceiver.getType();
- mn = findMethod(receiverType, name, args);
-
- // if receiver is "this" in a static context then only static methods are compatible
- // if not in a static context but the current receiver is a static class ensure that
- // all methods are either static or declared by the current receiver or a superclass
- if (!mn.isEmpty() && currentReceiver.getData() == null && (isThisObjectExpression || call.isImplicitThis())
- && (typeCheckingContext.isInStaticContext || (receiverType.getModifiers() & Opcodes.ACC_STATIC) != 0)) {
- // we create separate method lists just to be able to print out
- // a nice error message to the user
- // a method is accessible if it is static, or if we are not in a static context and it is
- // declared by the current receiver or a superclass
- List<MethodNode> accessibleMethods = new LinkedList<>();
- List<MethodNode> inaccessibleMethods = new LinkedList<>();
- for (final MethodNode node : mn) {
- if (node.isStatic() || (!typeCheckingContext.isInStaticContext
- && implementsInterfaceOrIsSubclassOf(receiverType, node.getDeclaringClass()))) {
- accessibleMethods.add(node);
- } else {
- inaccessibleMethods.add(node);
- }
- }
- mn = accessibleMethods;
- if (accessibleMethods.isEmpty()) {
- MethodNode node = inaccessibleMethods.get(0); // choose an arbitrary method to display an error message
- addStaticTypeError("Non-static method " + prettyPrintTypeName(node.getDeclaringClass()) + "#" + node.getName() + " cannot be called from static context", call);
+ mn = findMethod(currentReceiver.getType().getPlainNodeReference(), name, args);
+ if (!mn.isEmpty()) {
+ first = mn.get(0); // capture for error string
+ // for "this" in a static context, only static methods are compatible
+ if (currentReceiver.getData() == null && !isClassType(currentReceiver.getType())) {
+ boolean staticThis = (isThisObjectExpression || call.isImplicitThis()) && typeCheckingContext.isInStaticContext;
+ boolean staticThat = isClassClassNodeWrappingConcreteType(receiver); // GROOVY-10819, GROOVY-10820
+ mn = allowStaticAccessToMember(mn, staticThis || staticThat);
}
}
-
if (!mn.isEmpty()) {
chosenReceiver = currentReceiver;
break;
@@ -3517,19 +3502,17 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (mn.isEmpty() && isThisObjectExpression && call.isImplicitThis() && typeCheckingContext.getEnclosingClosure() != null) {
mn = CLOSURE_TYPE.getDeclaredMethods(name);
if (!mn.isEmpty()) {
- chosenReceiver = Receiver.make(CLOSURE_TYPE);
objectExpression.removeNodeMetaData(INFERRED_TYPE);
}
}
if (mn.isEmpty()) {
mn = extension.handleMissingMethod(receiver, name, argumentList, args, call);
+ if (mn.isEmpty() && first != null) mn.add(first); // non-static method error?
}
if (mn.isEmpty()) {
addNoMatchingMethodError(receiver, name, args, call);
} else {
- if (areCategoryMethodCalls(mn, name, args)) {
- addCategoryMethodCallError(call);
- }
+ if (areCategoryMethodCalls(mn, name, args)) addCategoryMethodCallError(call);
{
ClassNode obj = chosenReceiver != null ? chosenReceiver.getType() : null;
@@ -3548,8 +3531,11 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
if (mn.size() == 1) {
MethodNode targetMethodCandidate = mn.get(0);
ClassNode declaringClass = targetMethodCandidate.getDeclaringClass();
- if (!targetMethodCandidate.isStatic() && !isClassType(declaringClass)
- && objectExpression instanceof ClassExpression && call.getNodeMetaData(DYNAMIC_RESOLUTION) == null) {
+ if (chosenReceiver == null) {
+ chosenReceiver = Receiver.make(declaringClass.getPlainNodeReference());
+ }
+ if (!targetMethodCandidate.isStatic() && !isClassType(declaringClass) && isClassType(receiver)
+ && chosenReceiver.getData() == null && call.getNodeMetaData(DYNAMIC_RESOLUTION) == null) {
addStaticTypeError("Non-static method " + prettyPrintTypeName(declaringClass) + "#" + targetMethodCandidate.getName() + " cannot be called from static context", call);
} else if (targetMethodCandidate.isAbstract() && isSuperExpression(objectExpression)) { // GROOVY-10341
String target = toMethodParametersString(targetMethodCandidate.getName(), extractTypesFromParameters(targetMethodCandidate.getParameters()));
@@ -3559,9 +3545,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
addStaticTypeError("Abstract method " + target + " cannot be called directly", call);
}
}
- if (chosenReceiver == null) {
- chosenReceiver = Receiver.make(declaringClass);
- }
// note second pass here to differentiate from extension that sets type
boolean mergeType = (call.getNodeMetaData(INFERRED_TYPE) != null);
storeTargetMethod(call, targetMethodCandidate);
@@ -4966,11 +4949,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
methods.add(callMethod);
}
}
- if (!receiver.isStaticClass() && receiver.getOuterClass() != null
- && typeCheckingContext.getEnclosingClassNodes().contains(receiver)) {
- ClassNode outer = receiver.getOuterClass();
- do { methods.addAll(findMethodsWithGenerated(outer, name));
- } while (!outer.isStaticClass() && (outer = outer.getOuterClass()) != null);
+ if (typeCheckingContext.getEnclosingClassNodes().contains(receiver)) {
+ boolean staticOnly = Modifier.isStatic(receiver.getModifiers());
+ for (ClassNode outer = receiver; (outer = outer.getOuterClass()) != null;
+ staticOnly = staticOnly || Modifier.isStatic(outer.getModifiers())) {
+ methods.addAll(allowStaticAccessToMember(findMethodsWithGenerated(outer, name), staticOnly));
+ }
}
if (methods.isEmpty()) {
addArrayMethods(methods, receiver, name, args);
@@ -5034,7 +5018,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
}
- if (isClassClassNodeWrappingConcreteType(receiver)) { // GROOVY-6802, GROOVY-6803
+ if (isClassClassNodeWrappingConcreteType(receiver)) { // GROOVY-6802, GROOVY-6803, GROOVY-9415
List<MethodNode> result = findMethod(receiver.getGenericsTypes()[0].getType(), name, args);
if (!result.isEmpty()) return result;
}
@@ -5897,11 +5881,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
}
}
- protected void addNoMatchingMethodError(ClassNode receiver, final String name, final ClassNode[] args, final Expression call) {
- if (isClassClassNodeWrappingConcreteType(receiver)) {
- receiver = receiver.getGenericsTypes()[0].getType();
- }
- addStaticTypeError("Cannot find matching method " + prettyPrintTypeName(receiver) + "#" + toMethodParametersString(name, args) + ". Please check if the declared type is correct and if the method exists.", call);
+ protected void addNoMatchingMethodError(final ClassNode receiver, final String name, final ClassNode[] args, final Expression call) {
+ ClassNode type = isClassClassNodeWrappingConcreteType(receiver) ? receiver.getGenericsTypes()[0].getType() : receiver;
+ addStaticTypeError("Cannot find matching method " + prettyPrintTypeName(type) + "#" + toMethodParametersString(name, args) + ". Please check if the declared type is correct and if the method exists.", call);
}
protected void addAmbiguousErrorMessage(final List<MethodNode> foundMethods, final String name, final ClassNode[] args, final Expression expr) {
diff --git a/src/spec/test/typing/TypeCheckingTest.groovy b/src/spec/test/typing/TypeCheckingTest.groovy
index 75d85b92ee..84c18ac9ef 100644
--- a/src/spec/test/typing/TypeCheckingTest.groovy
+++ b/src/spec/test/typing/TypeCheckingTest.groovy
@@ -700,7 +700,8 @@ import static org.codehaus.groovy.ast.tools.WideningCategories.lowestUpperBound
}
// end::flowtyping_typeconstraints_failure[]
flowTypingWithExplicitType()
- ''', '[Static type checking] - Cannot find matching method java.util.ArrayList#add(int)'
+ ''',
+ 'Cannot call java.util.ArrayList#add(java.lang.String) with arguments [int]'
assertScript '''
// tag::flowtyping_typeconstraints_fixed[]
diff --git a/src/test/groovy/bugs/Groovy7204.groovy b/src/test/groovy/bugs/Groovy7204.groovy
index 67e5f1ff34..e68ecbf823 100644
--- a/src/test/groovy/bugs/Groovy7204.groovy
+++ b/src/test/groovy/bugs/Groovy7204.groovy
@@ -473,7 +473,7 @@ final class Groovy7204 {
'''
}
- @Test
+ @NotYetImplemented @Test
void testCompileStatic6() {
assertScript shell, '''
class Repository<T, S extends Serializable> {
@@ -482,7 +482,7 @@ final class Groovy7204 {
}
@CompileStatic
- def test() {
+ void test() {
Repository<String, Long> r = new Repository<String, Long>()
r.delete('foo')
}
diff --git a/src/test/groovy/bugs/Groovy7987.groovy b/src/test/groovy/bugs/Groovy7987.groovy
deleted file mode 100644
index 7f15e085b4..0000000000
--- a/src/test/groovy/bugs/Groovy7987.groovy
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package groovy.bugs
-
-import org.junit.Test
-
-import static groovy.test.GroovyAssert.shouldFail
-
-final class Groovy7987 {
-
- @Test
- void testNonStaticMethodViaStaticReceiver() {
- def err = shouldFail '''
- class Foo {
- def bar() {
- }
- }
-
- @groovy.transform.TypeChecked
- void test() {
- Foo.bar()
- }
-
- test()
- '''
- assert err =~ 'Non-static method Foo#bar cannot be called from static context'
- }
-}
diff --git a/src/test/groovy/bugs/Groovy8609Bug.groovy b/src/test/groovy/bugs/Groovy8609Bug.groovy
index 08720909fe..28bb9232eb 100644
--- a/src/test/groovy/bugs/Groovy8609Bug.groovy
+++ b/src/test/groovy/bugs/Groovy8609Bug.groovy
@@ -26,121 +26,118 @@ final class Groovy8609Bug extends GroovyTestCase {
void testUpperBoundWithGenerics() {
assertScript '''
- @groovy.transform.CompileStatic
- public class A<T extends List<E>, E extends Map<String, Integer>> {
- E getFirstRecord(T recordList) {
- return recordList.get(0)
+ @groovy.transform.CompileStatic
+ public class A<T extends List<E>, E extends Map<String, Integer>> {
+ E getFirstRecord(T recordList) {
+ return recordList.get(0)
+ }
+
+ static void main(args) {
+ def list = new ArrayList<HashMap<String, Integer>>()
+ def record = new HashMap<String, Integer>()
+ list.add(record)
+ def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
+ assert record.is(a.getFirstRecord(list))
+ }
}
-
- static void main(args) {
- def list = new ArrayList<HashMap<String, Integer>>()
- def record = new HashMap<String, Integer>()
- list.add(record)
- def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
- assert record.is(a.getFirstRecord(list))
- }
- }
'''
}
void testUpperBoundWithoutGenerics() {
assertScript '''
- @groovy.transform.CompileStatic
- public class A<T extends List<E>, E extends Map> {
- E getFirstRecord(T recordList) {
- return recordList.get(0);
- }
-
- static void main(args) {
- def list = new ArrayList<HashMap<String, Integer>>()
- def record = new HashMap<String, Integer>()
- list.add(record)
- def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
- assert record.is(a.getFirstRecord(list))
+ @groovy.transform.CompileStatic
+ public class A<T extends List<E>, E extends Map> {
+ E getFirstRecord(T recordList) {
+ return recordList.get(0);
+ }
+
+ static void main(args) {
+ def list = new ArrayList<HashMap<String, Integer>>()
+ def record = new HashMap<String, Integer>()
+ list.add(record)
+ def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
+ assert record.is(a.getFirstRecord(list))
+ }
}
- }
'''
}
void testNoUpperBound() {
assertScript '''
- @groovy.transform.CompileStatic
- public class A<T extends List<E>, E> {
- E getFirstRecord(T recordList) {
- return recordList.get(0);
+ @groovy.transform.CompileStatic
+ public class A<T extends List<E>, E> {
+ E getFirstRecord(T recordList) {
+ return recordList.get(0);
+ }
+
+ static void main(args) {
+ def list = new ArrayList<HashMap<String, Integer>>()
+ def record = new HashMap<String, Integer>()
+ list.add(record)
+ def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
+ assert record.is(a.getFirstRecord(list))
+ }
}
-
- static void main(args) {
- def list = new ArrayList<HashMap<String, Integer>>()
- def record = new HashMap<String, Integer>()
- list.add(record)
- def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
- assert record.is(a.getFirstRecord(list))
- }
- }
'''
}
void testUpperBoundWithGenericsThroughWrongType() {
- def errMsg = shouldFail '''
- @groovy.transform.CompileStatic
- public class A<T extends List<E>, E extends Map<String, Integer>> {
- E getFirstRecord(T recordList) {
- return recordList.get(0)
- }
-
- static void main(args) {
- def list = new ArrayList<TreeMap<String, Integer>>()
- def record = new TreeMap<String, Integer>()
- list.add(record)
- def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
- assert record.is(a.getFirstRecord(list))
+ def err = shouldFail '''
+ @groovy.transform.CompileStatic
+ public class A<T extends List<E>, E extends Map<String, Integer>> {
+ E getFirstRecord(T recordList) {
+ return recordList.get(0)
+ }
+
+ static void main(args) {
+ def list = new ArrayList<TreeMap<String, Integer>>()
+ def record = new TreeMap<String, Integer>()
+ list.add(record)
+ def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
+ assert record.is(a.getFirstRecord(list))
+ }
}
- }
'''
-
- assert errMsg.contains('[Static type checking] - Cannot find matching method A#getFirstRecord(java.util.ArrayList<java.util.TreeMap<java.lang.String, java.lang.Integer>>)')
+ assert err.contains('Cannot call A#getFirstRecord(java.util.ArrayList<java.util.HashMap<java.lang.String, java.lang.Integer>>) with arguments [java.util.ArrayList<java.util.TreeMap<java.lang.String, java.lang.Integer>>]')
}
void testUpperBoundWithGenericsThroughWrongType2() {
- def errMsg = shouldFail '''
- @groovy.transform.CompileStatic
- public class A<T extends List<E>, E extends Map<String, Integer>> {
- E getFirstRecord(T recordList) {
- return recordList.get(0)
- }
-
- static void main(args) {
- def list = new ArrayList<HashMap<String, Long>>()
- def record = new HashMap<String, Long>()
- list.add(record)
- def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
- assert record.is(a.getFirstRecord(list))
+ def err = shouldFail '''
+ @groovy.transform.CompileStatic
+ public class A<T extends List<E>, E extends Map<String, Integer>> {
+ E getFirstRecord(T recordList) {
+ return recordList.get(0)
+ }
+
+ static void main(args) {
+ def list = new ArrayList<HashMap<String, Long>>()
+ def record = new HashMap<String, Long>()
+ list.add(record)
+ def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
+ assert record.is(a.getFirstRecord(list))
+ }
}
- }
'''
-
- assert errMsg.contains('[Static type checking] - Cannot find matching method A#getFirstRecord(java.util.ArrayList<java.util.HashMap<java.lang.String, java.lang.Long>>)')
+ assert err.contains('Cannot call A#getFirstRecord(java.util.ArrayList<java.util.HashMap<java.lang.String, java.lang.Integer>>) with arguments [java.util.ArrayList<java.util.HashMap<java.lang.String, java.lang.Long>>]')
}
void testUpperBoundWithGenericsThroughWrongType3() {
- def errMsg = shouldFail '''
- @groovy.transform.CompileStatic
- public class A<T extends List<E>, E extends Map<String, Integer>> {
- E getFirstRecord(T recordList) {
- return recordList.get(0)
+ def err = shouldFail '''
+ @groovy.transform.CompileStatic
+ public class A<T extends List<E>, E extends Map<String, Integer>> {
+ E getFirstRecord(T recordList) {
+ return recordList.get(0)
+ }
+
+ static void main(args) {
+ def list = new ArrayList<HashMap<StringBuffer, Integer>>()
+ def record = new HashMap<StringBuffer, Integer>()
+ list.add(record)
+ def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
+ assert record.is(a.getFirstRecord(list))
+ }
}
-
- static void main(args) {
- def list = new ArrayList<HashMap<StringBuffer, Integer>>()
- def record = new HashMap<StringBuffer, Integer>()
- list.add(record)
- def a = new A<ArrayList<HashMap<String, Integer>>, HashMap<String, Integer>>()
- assert record.is(a.getFirstRecord(list))
- }
- }
'''
-
- assert errMsg.contains('[Static type checking] - Cannot find matching method A#getFirstRecord(java.util.ArrayList<java.util.HashMap<java.lang.StringBuffer, java.lang.Integer>>)')
+ assert err.contains('Cannot call A#getFirstRecord(java.util.ArrayList<java.util.HashMap<java.lang.String, java.lang.Integer>>) with arguments [java.util.ArrayList<java.util.HashMap<java.lang.StringBuffer, java.lang.Integer>>]')
}
}
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 3ecce489e4..f935323ee9 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -58,7 +58,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
List<String> list = []
list.add(1)
''',
- 'Cannot find matching method java.util.ArrayList#add(int)'
+ 'Cannot call java.util.ArrayList#add(java.lang.String) with arguments [int]'
}
void testAddOnList2() {
@@ -134,7 +134,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
List<Integer> list = new LinkedList<>()
list.add 'Hello'
''',
- 'Cannot find matching method java.util.LinkedList#add(java.lang.String). Please check if the declared type is correct and if the method exists.'
+ 'Cannot call java.util.LinkedList#add(java.lang.Integer) with arguments [java.lang.String]'
}
void testAddOnListWithDiamondAndWrongTypeUsingLeftShift() {
@@ -241,7 +241,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
Number number = Optional.of(42).orElse(Double.NaN)
assert number.intValue() == 42
''',
- 'Cannot find matching method java.util.Optional#orElse(double).'
+ 'Cannot call java.util.Optional#orElse(java.lang.Integer) with arguments [double]'
}
void testReturnTypeInferenceWithMethodGenerics5() {
@@ -257,7 +257,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
Number number = Optional.ofNullable((Integer) null).orElse(42d)
assert number.intValue() == 42
''',
- 'Cannot find matching method java.util.Optional#orElse(double).'
+ 'Cannot call java.util.Optional#orElse(java.lang.Integer) with arguments [double]'
}
void testReturnTypeInferenceWithMethodGenerics7() {
@@ -2079,7 +2079,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
def map = new HashMap<String, Integer>()
map.put('hello', new Object())
''',
- 'Cannot find matching method java.util.HashMap#put(java.lang.String, java.lang.Object). Please check if the declared type is correct and if the method exists.'
+ 'Cannot call java.util.HashMap#put(java.lang.String, java.lang.Integer) with arguments [java.lang.String, java.lang.Object]'
}
void testPutAtWithWrongValueType() {
@@ -2103,7 +2103,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
}
}
''',
- 'Cannot find matching method java.util.Map#put(java.lang.String, java.util.LinkedHashMap<java.lang.String, java.util.List<ConfigAttribute>>). Please check if the declared type is correct and if the method exists.',
+ 'Cannot call java.util.Map#put(java.lang.String, java.util.Map<java.lang.String, java.util.List<java.lang.String>>) with arguments [java.lang.String, java.util.LinkedHashMap<java.lang.String, java.util.List<ConfigAttribute>>]',
'Cannot call <K,V> org.codehaus.groovy.runtime.DefaultGroovyMethods#putAt(java.util.Map<K, V>, K, V) with arguments [java.util.Map<java.lang.String, java.util.Map<java.lang.String, java.util.List<java.lang.String>>>, java.lang.String, java.util.LinkedHashMap<java.lang.String, java.util.List<ConfigAttribute>>]'
}
@@ -2883,7 +2883,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
Map<Date, Date> map = new HashMap<>()
map.put('foo', new Date())
''',
- 'Cannot find matching method java.util.HashMap#put(java.lang.String, java.util.Date). Please check if the declared type is correct and if the method exists.'
+ 'Cannot call java.util.HashMap#put(java.util.Date, java.util.Date) with arguments [java.lang.String, java.util.Date]'
}
void testInferDiamondForAssignmentWithDatesAndIllegalKeyUsingSquareBracket() {
shouldFailWithMessages '''
@@ -2923,7 +2923,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
Map<Date, Date> map = new HashMap<>()
map.put(new Date(), 'foo')
''',
- 'Cannot find matching method java.util.HashMap#put(java.util.Date, java.lang.String). Please check if the declared type is correct and if the method exists.'
+ 'Cannot call java.util.HashMap#put(java.util.Date, java.util.Date) with arguments [java.util.Date, java.lang.String]'
}
void testInferDiamondForAssignmentWithDatesAndIllegalValueUsingSquareBracket() {
shouldFailWithMessages '''
@@ -3314,8 +3314,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
test(new Holder<Object>())
''',
'Cannot call TypedProperty#eq(java.lang.String) with arguments [groovy.lang.GString]',
- 'Cannot find matching method TypedProperty#eq(int)', // chooseBestMethod removes "eq"
- 'Cannot find matching method TypedProperty#eq(java.lang.String)'
+ 'Cannot call TypedProperty#eq(java.lang.String) with arguments [int]',
+ 'Cannot call TypedProperty#eq(java.lang.Number) with arguments [java.lang.String]'
}
// GROOVY-5748
diff --git a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
index 251bce0fdd..f53596a312 100644
--- a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -56,7 +56,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
shouldFailWithMessages '''
A a = new A()
assert a.foo(1,1)==2
- ''', 'Cannot find matching method'
+ ''',
+ 'Cannot find matching method'
}
void testMethodCallOnInstanceWithVarArgs() {
@@ -84,7 +85,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
void testMissingStaticMethod() {
shouldFailWithMessages '''
A.missing 'echo'
- ''', 'Cannot find matching method'
+ ''',
+ 'Cannot find matching method'
}
void testStaticMethodWithVarArgs() {
@@ -206,7 +208,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
B c = new B<Integer>()
String[] args = ['a','b','c']
assert c.identity(args) == args
- ''', 'Cannot call groovy.transform.stc.MethodCallsSTCTest$MyMethodCallTestClass2#identity(java.lang.Integer[]) with arguments [java.lang.String[]]'
+ ''',
+ 'Cannot call groovy.transform.stc.MethodCallsSTCTest$MyMethodCallTestClass2#identity(java.lang.Integer[]) with arguments [java.lang.String[]]'
}
// GROOVY-8909
@@ -222,7 +225,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
void m(Set<Integer> set) {
}
m([1,2,3,3])
- ''', 'm(java.util.List<java.lang.Integer>). Please check if the declared type is correct and if the method exists.'
+ ''',
+ 'm(java.util.List<java.lang.Integer>). Please check if the declared type is correct and if the method exists.'
}
// GROOVY-7106, GROOVY-7274, GROOVY-9844
@@ -384,7 +388,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
class Peer {
def foo() { new Main() }
}
- ''', '[Static type checking] - Cannot find matching method Main#<init>()'
+ ''',
+ 'Cannot find matching method Main#<init>()'
}
// GROOVY-8509
@@ -512,7 +517,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
bar(null, new Date())
}
}
- ''', 'Reference to method is ambiguous'
+ ''',
+ 'Reference to method is ambiguous'
}
// GROOVY-5175
@@ -572,7 +578,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
'Boolean'
}
['foo',123,true].each { foo(it) }
- ''', 'Cannot find matching method'
+ ''',
+ 'Cannot find matching method'
}
void testShouldNotFailThanksToInstanceOfChecks() {
@@ -660,7 +667,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
foo(it)
}
}
- ''', 'Reference to method is ambiguous'
+ ''',
+ 'Reference to method is ambiguous'
}
void testShouldFailWithMultiplePossibleMethods2() {
@@ -679,7 +687,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
foo(argument)
}
}
- ''', 'Reference to method is ambiguous'
+ ''',
+ 'Reference to method is ambiguous'
}
// GROOVY-5703
@@ -781,7 +790,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
it = new Date()
foo(it)
}
- ''', 'foo(java.util.Date)'
+ ''',
+ 'foo(java.util.Date)'
}
void testShouldNotFailEvenIfVariableIsReassigned() {
@@ -832,7 +842,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
return val.toUpperCase()
}
assert m(123) == 'HELLO'
- ''', '#m(int)'
+ ''',
+ '#m(int)'
}
void testOneDefaultParamAndOneWithout() {
@@ -851,7 +862,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
return val.toUpperCase() + append
}
m('test', new Object())
- ''', 'm(java.lang.String, java.lang.Object)'
+ ''',
+ 'm(java.lang.String, java.lang.Object)'
}
void testMultipleDefaultArgs() {
@@ -880,7 +892,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
return first.toUpperCase() + ' ' + second + ' ' + third.toUpperCase()
}
m('f',123,'s', 'too many args')
- ''', '#m(java.lang.String, int, java.lang.String, java.lang.String)'
+ ''',
+ '#m(java.lang.String, int, java.lang.String, java.lang.String)'
}
void testMultipleDefaultArgsWithMixedTypesAndWrongType() {
@@ -889,7 +902,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
return first.toUpperCase() + ' ' + second + ' ' + third.toUpperCase()
}
m('hello') // no value set for "second"
- ''', '#m(java.lang.String)'
+ ''',
+ '#m(java.lang.String)'
}
void testShouldNotFailWithAmbiguousMethodSelection() {
@@ -915,7 +929,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
shouldFailWithMessages '''
float square(float x) { x*x }
assert square(2.0d) == 4.0d
- ''', '#square(double)'
+ ''',
+ '#square(double)'
}
void testShouldNotBeAbleToCallMethodUsingLongWithFloatOrDouble() {
@@ -923,31 +938,34 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
float square(long x) { x*x }
assert square(2.0d) == 4.0d
assert square(2.0f) == 4.0d
- ''', '#square(double)', '#square(float)'
+ ''',
+ '#square(double)', '#square(float)'
}
- void testShouldNotAllowMethodCallFromStaticContext() {
+ void testShouldNotAllowMethodCallFromStaticInitializer() {
shouldFailWithMessages '''
class A {
void instanceMethod() {}
- static void staticMethod() {
- instanceMethod() // calling instance method from static context
+ static {
+ instanceMethod()
}
}
- A.staticMethod()
- ''', 'Non-static method A#instanceMethod cannot be called from static context'
+ new A()
+ ''',
+ 'Non-static method A#instanceMethod cannot be called from static context'
}
- void testShouldNotAllowMethodCallFromStaticConstructor() {
+ void testShouldNotAllowMethodCallFromStaticMethod() {
shouldFailWithMessages '''
class A {
void instanceMethod() {}
- static {
- instanceMethod() // calling instance method from static context
+ static void staticMethod() {
+ instanceMethod()
}
}
- new A()
- ''', 'Non-static method A#instanceMethod cannot be called from static context'
+ A.staticMethod()
+ ''',
+ 'Non-static method A#instanceMethod cannot be called from static context'
}
void testShouldNotAllowMethodCallFromStaticField() {
@@ -957,7 +975,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
static FOO = instanceMethod()
}
new A()
- ''', 'Non-static method A#instanceMethod cannot be called from static context'
+ ''',
+ 'Non-static method A#instanceMethod cannot be called from static context'
}
// GROOVY-5495
@@ -1600,11 +1619,13 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
void testMoreExplicitErrorMessageOnStaticMethodNotFound() {
shouldFailWithMessages '''
Double.isFiniteMissing(2.0d)
- ''', 'Cannot find matching method java.lang.Double#isFiniteMissing(double)'
+ ''',
+ 'Cannot find matching method java.lang.Double#isFiniteMissing(double)'
shouldFailWithMessages '''
String.doSomething()
- ''', 'Cannot find matching method java.lang.String#doSomething()'
+ ''',
+ 'Cannot find matching method java.lang.String#doSomething()'
}
// GROOVY-6776
@@ -1615,7 +1636,8 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
foo null
}
bar()
- ''', '#foo(int) with arguments [<unknown parameter type>]'
+ ''',
+ '#foo(int) with arguments [<unknown parameter type>]'
}
// GROOVY-6751
@@ -1637,49 +1659,58 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
'''
}
+ // GROOVY-7987
+ void testNonStaticMethodViaStaticReceiver() {
+ shouldFailWithMessages '''
+ class Foo {
+ def m() {}
+ }
+ Foo.m()
+ ''',
+ 'Non-static method Foo#m cannot be called from static context'
+ }
+
// GROOVY-7813
void testNonStaticOuterMethodCannotBeCalledFromStaticClass() {
shouldFailWithMessages '''
class Foo {
- def bar() { 2 }
-
- static class Baz {
- def doBar() { bar() }
+ def m() {}
+ static class Bar {
+ void test() { m() }
}
}
- null
- ''', 'Non-static method Foo#bar cannot be called from static context'
+ ''',
+ 'Cannot find matching method Foo$Bar#m()'
}
void testStaticOuterMethodCanBeCalledFromStaticClass() {
assertScript '''
class Foo {
- static def bar() { 2 }
-
- static class Baz {
- def doBar() {
- bar()
+ static def sm() { 2 }
+ static class Bar {
+ void test() {
+ assert sm() == 2
}
}
}
- assert new Foo.Baz().doBar() == 2
+ new Foo.Bar().test()
'''
}
void testInheritedMethodCanBeCalledFromStaticClass() {
assertScript '''
- class Bar {
- def bar() { 1 }
+ class Foo {
+ def m() { 1 }
}
- class Foo {
- static class Baz extends Bar {
- def doBar() {
- bar()
+ class Bar {
+ static class Baz extends Foo {
+ void test() {
+ assert m() == 1
}
}
}
- assert new Foo.Baz().doBar() == 1
+ new Bar.Baz().test()
'''
}
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
index c78f02a04a..1c26771c7f 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
@@ -49,8 +49,7 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
// GROOVY-5512
void testCreateRangeInInnerClass() {
- def shell = new GroovyShell()
- shell.evaluate '''
+ new GroovyShell().evaluate '''
class Outer {
static class Inner {
@groovy.transform.CompileStatic
@@ -67,54 +66,46 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
// GROOVY-5526
void testAssertEqualsShouldNotThrowVerifyError() {
- assertScript '''
- import static org.junit.Assert.*;
- import groovy.transform.CompileStatic;
-
+ assertScript '''import static org.junit.Assert.*
class CompilerBugs {
-
- public static void main(String[] args) {
- int expected = 0
- assertEquals(expected, args.length)
- }
-
+ public static void main(String[] args) {
+ int expected = 0
+ assertEquals(expected, args.length)
+ }
}
'''
}
// GROOVY-5529
void testStaticCompilationOfClosureWhenSingleMethodAnnotated() {
- new GroovyShell().evaluate '''import groovy.transform.ASTTest
- import static org.codehaus.groovy.control.CompilePhase.*
-
- interface Row {
- int getKey()
- }
-
- class RowImpl implements Row {
- int getKey() { 1 }
- }
+ new GroovyShell().evaluate '''
+ interface Row {
+ int getKey()
+ }
- @groovy.transform.CompileStatic
- def test() {
- def rows = [new RowImpl(), new RowImpl(), new RowImpl()]
+ class RowImpl implements Row {
+ int getKey() { 1 }
+ }
- rows.each { Row row ->
- println row.key
+ @groovy.transform.CompileStatic
+ def test() {
+ def rows = [new RowImpl(), new RowImpl(), new RowImpl()]
+ rows.each { Row row ->
+ println row.key
+ }
}
- }
- test()
+ test()
'''
}
// GROOVY-5536
void testShouldNotThrowVerifyErrorWithNullDereferenceInIf() {
assertScript '''
- boolean getDescriptorForPlugin(File pluginDir) {
- if (pluginDir?.exists()) { true } else { false }
- }
- assert getDescriptorForPlugin(null) == false
+ boolean getDescriptorForPlugin(File pluginDir) {
+ if (pluginDir?.exists()) { true } else { false }
+ }
+ assert getDescriptorForPlugin(null) == false
'''
}
@@ -138,7 +129,8 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
// GROOVY-
void testPowerShouldNotThrowVerifyError() {
- assertScript '''int squarePlusOne(int num) {
+ assertScript '''
+ int squarePlusOne(int num) {
num ** num + 1
}
assert squarePlusOne(2) == 5
@@ -148,17 +140,17 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
// GROOVY-5570
void testShouldNotThrowVerifyErrorRegisterContainsWrongType() {
assertScript '''
- void foo() {
+ void foo() {
boolean idx = false
def cl = { idx }
- }
- '''
+ }
+ '''
assertScript '''
- void foo() {
+ void foo() {
int idx = 0
def cl = { idx }
- }
- '''
+ }
+ '''
}
// GROOVY-5572
@@ -212,7 +204,6 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
}
}
- @groovy.transform.CompileStatic
class Main {
void test() {
@ASTTest(phase=INSTRUCTION_SELECTION, value={
@@ -228,104 +219,104 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
void testCompileStaticTwiceShouldNotBeAProblem() {
new GroovyShell().evaluate '''import groovy.transform.CompileStatic
- @CompileStatic
- class Tool {
- @CompileStatic // annotated too, even if class is already annotated
- String relativePath(File relbase, File file) {
- def pathParts = []
- def currentFile = file
- while (currentFile != null && currentFile != relbase) {
- pathParts += currentFile.name
- currentFile = currentFile.parentFile
+ @CompileStatic
+ class Tool {
+ @CompileStatic // annotated too, even if class is already annotated
+ String relativePath(File relbase, File file) {
+ def pathParts = []
+ def currentFile = file
+ while (currentFile != null && currentFile != relbase) {
+ pathParts += currentFile.name
+ currentFile = currentFile.parentFile
+ }
+ pathParts.reverse().join('/')
}
- pathParts.reverse().join('/')
}
- }
- File a = new File('foo')
- File b = new File(new File(a, 'bar'), 'baz')
- assert new Tool().relativePath(a,b) == 'bar/baz'
+ File a = new File('foo')
+ File b = new File(new File(a, 'bar'), 'baz')
+ assert new Tool().relativePath(a,b) == 'bar/baz'
'''
}
void testCompileStaticTwiceShouldNotBeAProblemUsingCustomizer() {
- assertScript '''import groovy.transform.CompileStatic
- @CompileStatic
- class Tool {
- @CompileStatic // annotated too, even if class is already annotated
- String relativePath(File relbase, File file) {
- def pathParts = []
- def currentFile = file
- while (currentFile != null && currentFile != relbase) {
- pathParts += currentFile.name
- currentFile = currentFile.parentFile
+ assertScript '''
+ @CompileStatic
+ class Tool {
+ @CompileStatic // annotated too, even if class is already annotated
+ String relativePath(File relbase, File file) {
+ def pathParts = []
+ def currentFile = file
+ while (currentFile != null && currentFile != relbase) {
+ pathParts += currentFile.name
+ currentFile = currentFile.parentFile
+ }
+ pathParts.reverse().join('/')
}
- pathParts.reverse().join('/')
}
- }
- File a = new File('foo')
- File b = new File(new File(a, 'bar'), 'baz')
- assert new Tool().relativePath(a,b) == 'bar/baz'
+ File a = new File('foo')
+ File b = new File(new File(a, 'bar'), 'baz')
+ assert new Tool().relativePath(a,b) == 'bar/baz'
'''
}
// GROOVY-5613
void testNullSafeAssignment() {
assertScript '''
- class A {
- int x = -1
- }
- A a = new A()
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- assert node.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
- })
- def x = a?.x
+ class A {
+ int x = -1
+ }
+ A a = new A()
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ assert node.getNodeMetaData(INFERRED_TYPE) == Integer_TYPE
+ })
+ def x = a?.x
'''
}
void testNullSafeAssignmentWithLong() {
assertScript '''
- class A {
- long x = -1
- }
- A a = new A()
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- assert node.getNodeMetaData(INFERRED_TYPE) == Long_TYPE
- })
- def x = a?.x
+ class A {
+ long x = -1
+ }
+ A a = new A()
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ assert node.getNodeMetaData(INFERRED_TYPE) == Long_TYPE
+ })
+ def x = a?.x
'''
}
void testNullSafeAssignmentWithChar() {
assertScript '''
- class A {
- char x = 'a'
- }
- A a = new A()
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- assert node.getNodeMetaData(INFERRED_TYPE) == Character_TYPE
- })
- def x = a?.x
- assert x == 'a'
+ class A {
+ char x = 'a'
+ }
+ A a = new A()
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ assert node.getNodeMetaData(INFERRED_TYPE) == Character_TYPE
+ })
+ def x = a?.x
+ assert x == 'a'
'''
}
void testCallStaticallyImportedMethodWithNullSafeArgument() {
assertScript '''import static java.lang.Math.abs
- class A {
- int x = -1
- }
- def a = new A()
- def x = a?.x
- assert abs(a?.x) == 1
+ class A {
+ int x = -1
+ }
+ def a = new A()
+ def x = a?.x
+ assert abs(a?.x) == 1
'''
}
void testClosureAsInterfaceArgument() {
assertScript '''
- Closure c = { Integer x, Integer y -> x <=> y }
- def list = [ 3,1,5,2,4 ]
- assert ((Collection)list).sort(c) == [1,2,3,4,5]
- '''
+ Closure c = { Integer x, Integer y -> x <=> y }
+ def list = [ 3,1,5,2,4 ]
+ assert ((Collection)list).sort(c) == [1,2,3,4,5]
+ '''
}
void testInferredTypeForInteger() {
@@ -351,35 +342,35 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
void testPostfixIncInteger() {
assertScript '''
- Integer x = 0
- x++
- x++
- assert x == 2
- assert x++ == 2
- assert x == 3
- '''
+ Integer x = 0
+ x++
+ x++
+ assert x == 2
+ assert x++ == 2
+ assert x == 3
+ '''
}
void testPostfixDecInt() {
assertScript '''
- int x = 0
- x--
- x--
- assert x == -2
- assert x-- == -2
- assert x == -3
- '''
+ int x = 0
+ x--
+ x--
+ assert x == -2
+ assert x-- == -2
+ assert x == -3
+ '''
}
void testPostfixDecInteger() {
assertScript '''
- Integer x = 0
- x--
- x--
- assert x == -2
- assert x-- == -2
- assert x == -3
- '''
+ Integer x = 0
+ x--
+ x--
+ assert x == -2
+ assert x-- == -2
+ assert x == -3
+ '''
}
void testPrefixIncPrimitiveInteger() {
@@ -395,42 +386,42 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
void testPrefixIncInteger() {
assertScript '''
- Integer x = 0
- ++x
- ++x
- assert x == 2
- assert ++x == 3
- assert x == 3
- '''
+ Integer x = 0
+ ++x
+ ++x
+ assert x == 2
+ assert ++x == 3
+ assert x == 3
+ '''
}
void testPrefixDecInt() {
assertScript '''
- int x = 0
- --x
- --x
- assert --x == -3
- assert x == -3
- '''
+ int x = 0
+ --x
+ --x
+ assert --x == -3
+ assert x == -3
+ '''
}
void testPrefixDecInteger() {
assertScript '''
- Integer x = 0
- --x
- --x
- assert --x == -3
- assert x == -3
- '''
+ Integer x = 0
+ --x
+ --x
+ assert --x == -3
+ assert x == -3
+ '''
}
void testShouldSkipSpreadOperator() {
- new GroovyShell().evaluate '''import groovy.transform.TypeCheckingMode
- import groovy.transform.CompileStatic
+ new GroovyShell().evaluate '''import groovy.transform.CompileStatic
+ import static groovy.transform.TypeCheckingMode.SKIP
@CompileStatic // top level must be @CS
class Foo {
- @CompileStatic(TypeCheckingMode.SKIP)
+ @CompileStatic(SKIP)
static void foo(fun, args) {
new Runnable() { // create an anonymous class which should *not* be visited
void run() {
@@ -445,16 +436,14 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
// GROOVY-5672
void testTypeCheckedPlusCompileStatic() {
- new GroovyShell().evaluate '''import groovy.transform.CompileStatic
- import groovy.transform.TypeChecked
-
- @TypeChecked
- @CompileStatic
- class SampleClass {
- def a = "some string"
- def b = a.toString()
- }
- new SampleClass()
+ new GroovyShell().evaluate '''import groovy.transform.*
+ @TypeChecked
+ @CompileStatic
+ class SampleClass {
+ def a = "some string"
+ def b = a.toString()
+ }
+ new SampleClass()
'''
}
@@ -479,79 +468,86 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
void testIncrementOperatorOnInt() {
assertScript '''
- int incInt(int n) {
- def result = n
- ++result
- result++
- return result
- }
- assert incInt(5) == 7'''
+ int incInt(int n) {
+ def result = n
+ ++result
+ result++
+ return result
+ }
+ assert incInt(5) == 7
+ '''
}
void testIncrementOperatorOnShort() {
assertScript '''
- short incInt(short n) {
- def result = n
- ++result
- result++
- return result
- }
- assert incInt((short)5) == 7'''
+ short incInt(short n) {
+ def result = n
+ ++result
+ result++
+ return result
+ }
+ assert incInt((short)5) == 7
+ '''
}
void testIncrementOperatorOnByte() {
assertScript '''
- byte incInt(byte n) {
- def result = n
- ++result
- result++
- return result
- }
- assert incInt((byte)5) == 7'''
+ byte incInt(byte n) {
+ def result = n
+ ++result
+ result++
+ return result
+ }
+ assert incInt((byte)5) == 7
+ '''
}
void testIncrementOperatorOnLong() {
assertScript '''
- long incInt(long n) {
- def result = n
- ++result
- result++
- return result
- }
- assert incInt(5) == 7'''
+ long incInt(long n) {
+ def result = n
+ ++result
+ result++
+ return result
+ }
+ assert incInt(5) == 7
+ '''
}
void testIncrementOperatorOnFloat() {
assertScript '''
- float incInt(float n) {
- def result = n
- ++result
- result++
- return result
- }
- assert incInt(5) == 7'''
+ float incInt(float n) {
+ def result = n
+ ++result
+ result++
+ return result
+ }
+ assert incInt(5) == 7
+ '''
}
void testIncrementOperatorOnDouble() {
assertScript '''
- double incInt(double n) {
- def result = n
- ++result
- result++
- return result
- }
- assert incInt(5) == 7'''
+ double incInt(double n) {
+ def result = n
+ ++result
+ result++
+ return result
+ }
+ assert incInt(5) == 7
+ '''
}
void testIncrementOperatorOnChar() {
assertScript '''
- char incInt(char n) {
- def result = n
- ++result
- result++
- return result
- }
- assert incInt((char)'a') == (char)('c')'''
+ char incInt(char n) {
+ def result = n
+ ++result
+ result++
+ return result
+ }
+ assert incInt((char)'a') == (char)('c')
+ '''
}
void testIncrementField() {
@@ -570,13 +566,13 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
// GROOVY-5789
void testLoopWithIncrement() {
assertScript '''
- int execute() {
- // using a list, so that if the loop is endless, the test eventually fails with OOM
- List<Integer> list = new LinkedList<Integer>()
- for (def i = 0; i < 4; ++i) { println i; list << i }
- list.size()
- }
- assert execute() == 4
+ int execute() {
+ // using a list, so that if the loop is endless, the test eventually fails with OOM
+ List<Integer> list = new LinkedList<Integer>()
+ for (def i = 0; i < 4; ++i) { println i; list << i }
+ list.size()
+ }
+ assert execute() == 4
'''
}
@@ -588,7 +584,7 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
}
assert m(1) == true
assert m(4) == false
- '''
+ '''
}
// GROOVY-5814
@@ -650,16 +646,16 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
// GROOVY-5804
void testNegateSharedBooleanInClosure() {
assertScript '''
- boolean x = false
- def cl = {
- if (!x) {
- assert true
- } else {
- assert false
- }
+ boolean x = false
+ def cl = {
+ if (!x) {
+ assert true
+ } else {
+ assert false
}
- cl()
- '''
+ }
+ cl()
+ '''
}
void testCallClosureInInnerClass() {
@@ -711,13 +707,12 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
}
void testSuperMethodCallInSkippedSection() {
- assertScript '''import groovy.transform.CompileStatic
-import groovy.transform.TypeCheckingMode
+ assertScript '''
class Top {
public int foo() { 123 }
}
class Bottom extends Top {
- @CompileStatic(TypeCheckingMode.SKIP)
+ @CompileStatic(SKIP)
public int bar() {
foo()
}
@@ -732,7 +727,8 @@ import groovy.transform.TypeCheckingMode
def foo(Object o) {
o[0]
}
- ''', 'Cannot find matching method java.lang.Object#getAt(int)'
+ ''',
+ 'Cannot find matching method java.lang.Object#getAt(int)'
}
void testStaticCompileWithPattern() {
@@ -745,25 +741,26 @@ import groovy.transform.TypeCheckingMode
def value = fieldMatcher[0]
// should not pass
def str = value[0]
- ''', 'Cannot find matching method java.lang.Object#getAt(int)'
+ ''',
+ 'Cannot find matching method java.lang.Object#getAt(int)'
}
void testChainedNullSafePropertyOnMap() {
assertScript '''
- Map<String, Map<String,Map<String,Integer>>> m=[:]
- // this is ok
- assert m?.a == null
- assert m?.a?.b == null
- assert m?.a?.b?.c == null
- assert m?.a?.b?.c?.intValue() == null
+ Map<String, Map<String,Map<String,Integer>>> m = [:]
+ // this is ok
+ assert m?.a == null
+ assert m?.a?.b == null
+ assert m?.a?.b?.c == null
+ assert m?.a?.b?.c?.intValue() == null
'''
}
void testNullSafePropertyOnList() {
assertScript '''
- List<Class> classes = null
- // this is ok
- assert classes?.name == null
+ List<Class> classes = null
+ // this is ok
+ assert classes?.name == null
'''
}
@@ -784,21 +781,21 @@ import groovy.transform.TypeCheckingMode
// GROOVY-6101
void testShouldNotGenerateInvalidClassWithNullSafeInvocationOnMethodReturningPrimitiveType() {
assertScript '''
- class Piece {
- int x() { 333 }
- }
+ class Piece {
+ int x() { 333 }
+ }
- void foo() {
- Piece[] pieces = [new Piece(), null] as Piece[]
- int sum = 0
- for (int i=0;i<pieces.length;i++) {
- if (pieces[i]?.x()) {
- sum += pieces[i].x()
+ void foo() {
+ Piece[] pieces = [new Piece(), null] as Piece[]
+ int sum = 0
+ for (int i=0;i<pieces.length;i++) {
+ if (pieces[i]?.x()) {
+ sum += pieces[i].x()
+ }
}
+ assert sum == 333
}
- assert sum == 333
- }
- foo()
+ foo()
'''
}
@@ -841,7 +838,6 @@ import groovy.transform.TypeCheckingMode
def b = new Groovy5921()
b.doSomething()
-
'''
}
@@ -857,7 +853,6 @@ import groovy.transform.TypeCheckingMode
def b = new Groovy5921()
b.doSomething()
-
'''
}
@@ -873,7 +868,6 @@ import groovy.transform.TypeCheckingMode
def b = new Groovy5921()
b.doSomething()
-
'''
}
@@ -889,7 +883,6 @@ import groovy.transform.TypeCheckingMode
def b = new Groovy5921()
b.doSomething()
-
'''
}
@@ -931,24 +924,20 @@ import groovy.transform.TypeCheckingMode
// GROOVY-6095
void testServletError() {
- assertScript '''
+ new GroovyShell().evaluate '''
@Grab('javax.servlet:javax.servlet-api:3.0.1')
- import groovy.transform.CompileStatic
-
import javax.servlet.ServletContext
import javax.servlet.ServletRegistration
/**
* author: Richard Vowles - http://gplus.to/RichardVowles
*/
- @CompileStatic
+ @groovy.transform.CompileStatic
class ServletExample {
-
public void myMethod(ServletContext ctx) {
ctx.getServletRegistrations().each { String name, ServletRegistration sr ->
println name
}
-
}
}
new ServletExample()
@@ -958,67 +947,67 @@ import groovy.transform.TypeCheckingMode
// GROOVY-6137
void testIsCaseShouldBeNullSafe() {
assertScript '''
- def isCaseNullCS(a, b) {
- a in b
- }
- assert isCaseNullCS(1, null) == false
- assert isCaseNullCS(null, 1) == false
- assert isCaseNullCS(1,1) == true
- assert isCaseNullCS(1,2) == false
- assert isCaseNullCS(2,1) == false
+ def isCaseNullCS(a, b) {
+ a in b
+ }
+ assert isCaseNullCS(1, null) == false
+ assert isCaseNullCS(null, 1) == false
+ assert isCaseNullCS(1,1) == true
+ assert isCaseNullCS(1,2) == false
+ assert isCaseNullCS(2,1) == false
'''
}
// GROOVY-6242
void testGetAtBigInt() {
assertScript '''
-class Sequence {
- public Sequence() {}
- static BigInteger getAt(final int index) { 1G }
- static BigInteger getAt(final BigInteger index) { getAt(index as int) }
-}
-
-class Iterator implements java.util.Iterator {
- private BigInteger currentIndex = 0G
- private final Sequence sequence
- Iterator(final Sequence s) { sequence = s }
- boolean hasNext() { return true }
- @ASTTest(phase=INSTRUCTION_SELECTION,value={
- def expr = node.code.statements[0].expression
- def indexType = expr.rightExpression.getNodeMetaData(INFERRED_TYPE)
- assert indexType == make(BigInteger)
- })
- BigInteger next() { sequence[currentIndex++] }
- void remove() { throw new UnsupportedOperationException() }
-}
+ class Sequence {
+ public Sequence() {}
+ static BigInteger getAt(final int index) { 1G }
+ static BigInteger getAt(final BigInteger index) { getAt(index as int) }
+ }
+
+ class Iterator implements java.util.Iterator {
+ private BigInteger currentIndex = 0G
+ private final Sequence sequence
+ Iterator(final Sequence s) { sequence = s }
+ boolean hasNext() { return true }
+ @ASTTest(phase=INSTRUCTION_SELECTION,value={
+ def expr = node.code.statements[0].expression
+ def indexType = expr.rightExpression.getNodeMetaData(INFERRED_TYPE)
+ assert indexType == make(BigInteger)
+ })
+ BigInteger next() { sequence[currentIndex++] }
+ void remove() { throw new UnsupportedOperationException() }
+ }
-def it = new Iterator(new Sequence())
-assert it.next() == 1G
-'''
+ def it = new Iterator(new Sequence())
+ assert it.next() == 1G
+ '''
}
// GROOVY-6243
void testSwapUsingMultipleAssignment() {
assertScript '''
- def swap(result,next) {
- print "($result,$next) -> "
- (result, next) = [next, result]
- println "($result,$next)"
- [result, next]
- }
+ def swap(result,next) {
+ print "($result,$next) -> "
+ (result, next) = [next, result]
+ println "($result,$next)"
+ [result, next]
+ }
- assert swap(0,1) == [1,0]
- assert swap('a','b') == ['b','a']
- assert swap('a', 1) == [1, 'a']
- def o1 = new Object()
- def o2 = new Date()
- assert swap(o1,o2) == [o2, o1]
+ assert swap(0,1) == [1,0]
+ assert swap('a','b') == ['b','a']
+ assert swap('a', 1) == [1, 'a']
+ def o1 = new Object()
+ def o2 = new Date()
+ assert swap(o1,o2) == [o2, o1]
'''
}
// GROOVY-5882
void testMod() {
- assertScript """
+ assertScript '''
int foo(Map<Integer, Object> markers, int i) {
int res = 0
for (e in markers.entrySet()) {
@@ -1027,9 +1016,9 @@ assert it.next() == 1G
return res
}
assert foo([(1):null,(2):null,(3):null],2)==2
- """
+ '''
- assertScript """
+ assertScript '''
int foo(Map<Integer, Object> markers, int i) {
int res = 0
for (e in markers.entrySet()) {
@@ -1039,8 +1028,8 @@ assert it.next() == 1G
return res
}
assert foo([(1):null,(2):null,(3):null],2)==2
- """
- assertScript """
+ '''
+ assertScript '''
int foo(Map<Integer, Object> markers, int i) {
int res = 0
for (e in markers.entrySet()) {
@@ -1049,7 +1038,7 @@ assert it.next() == 1G
return res
}
assert foo([(1):null,(2):null,(3):null],2)==2
- """
+ '''
}
void testSuperCallShouldBeDirect() {
@@ -1088,7 +1077,7 @@ assert it.next() == 1G
println seq.next?.longValue()
}
assert seq.next == 5
-'''
+ '''
}
void testNullSafeOperatorShouldNotCallMethodTwiceWithPrimitive() {
@@ -1108,7 +1097,7 @@ assert it.next() == 1G
println seq.next?.longValue()
}
assert seq.next == 5
-'''
+ '''
}
void testNullSafeOperatorShouldNotCallMethodTwice1Arg() {
@@ -1128,7 +1117,7 @@ assert it.next() == 1G
println seq.getNext(2)?.longValue()
}
assert seq.getNext(2) == 10
-'''
+ '''
}
void testNullSafeOperatorShouldNotCallMethodTwiceWithPrimitive1Arg() {
@@ -1148,7 +1137,7 @@ assert it.next() == 1G
println seq.getNext(2)?.longValue()
}
assert seq.getNext(2) == 10
-'''
+ '''
}
void testShouldAllowSubscriptOperatorOnSet() {
@@ -1180,21 +1169,20 @@ assert it.next() == 1G
// GROOVY-6552
void testShouldNotThrowClassCastException() {
assertScript '''import java.util.concurrent.Callable
-
- String text(Class clazz) {
- new Callable<String>() {
- String call() throws Exception {
+ String text(Class clazz) {
new Callable<String>() {
String call() throws Exception {
- clazz.getName()
+ new Callable<String>() {
+ String call() throws Exception {
+ clazz.getName()
+ }
+ }.call()
}
}.call()
}
- }.call()
- }
- assert text(String) == 'java.lang.String'
- '''
+ assert text(String) == 'java.lang.String'
+ '''
}
// GROOVY-6851
@@ -1212,19 +1200,19 @@ assert it.next() == 1G
}
}
new GrailsHomeWorkspaceReader()
- '''
+ '''
}
// GROOVY-6342
void testShouldNotThrowNPEIfElvisOperatorIsUsedInsideTernary() {
- assertScript '''class Inner {
- int somestuff
-}
-Inner inner = null
-int someInt = inner?.somestuff ?: 0
-println someInt
-
-'''
+ assertScript '''
+ class Inner {
+ int somestuff
+ }
+ Inner inner = null
+ int someInt = inner?.somestuff ?: 0
+ println someInt
+ '''
}
void testAccessOuterClassMethodFromInnerClassConstructor() {
@@ -1381,26 +1369,26 @@ println someInt
void testShouldNotThrowIncompatibleClassChangeError() {
try {
assertScript '''import org.codehaus.groovy.classgen.asm.sc.Groovy6924Support
- class Test {
- static void foo() {
- Groovy6924Support bean = new Groovy6924Support()
- bean.with {
- foo = 'foo'
- bar = 'bar'
+ class Test {
+ static void foo() {
+ Groovy6924Support bean = new Groovy6924Support()
+ bean.with {
+ foo = 'foo'
+ bar = 'bar'
+ }
+ String val = "$bean.foo and $bean.bar"
+ assert val == 'foo and bar'
}
- String val = "$bean.foo and $bean.bar"
- assert val == 'foo and bar'
}
- }
- Test.foo()
- '''
+ Test.foo()
+ '''
} finally {
assert astTrees['Test$_foo_closure1'][1].contains('INVOKEVIRTUAL org/codehaus/groovy/classgen/asm/sc/Groovy6924Support.setFoo (Ljava/lang/String;)V')
}
}
// GROOVY-7381
- void testNonVoidSetterCalls(){
+ void testNonVoidSetterCalls() {
assertScript '''
class Foo {
int num
@@ -1523,4 +1511,21 @@ println someInt
test()
'''
}
+
+ // GROOVY-10819, GROOVY-10820
+ void testClassVersusObjectMethods() {
+ assertScript '''
+ assert String.metaClass != Class.metaClass
+ assert String.metaClass != Class.getMetaClass()
+ assert String.getMetaClass() != Class.getMetaClass()
+ '''
+ assertScript '''
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ def source = node.rightExpression // "String.getMetaClass()"
+ def target = source.getNodeMetaData(DIRECT_METHOD_CALL_TARGET)
+ assert target.declaringClass == CLASS_Type // not OBJECT_TYPE!
+ })
+ def smc = String.getMetaClass()
+ '''
+ }
}
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTestSupport.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTestSupport.groovy
index 0f9a644822..7b67973346 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTestSupport.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/StaticCompilationTestSupport.groovy
@@ -56,10 +56,12 @@ trait StaticCompilationTestSupport {
new ImportCustomizer().tap {
addImports(
'groovy.transform.ASTTest',
+ 'groovy.transform.CompileStatic',
'groovy.transform.stc.ClosureParams',
'org.codehaus.groovy.ast.ClassHelper',
'org.codehaus.groovy.transform.stc.StaticTypesMarker')
addStaticStars(
+ 'groovy.transform.TypeCheckingMode',
'org.codehaus.groovy.ast.ClassHelper',
'org.codehaus.groovy.control.CompilePhase',
'org.codehaus.groovy.transform.stc.StaticTypesMarker')
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Console.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Console.groovy
index bc1b9a66f9..c78aac38e0 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Console.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Console.groovy
@@ -1426,26 +1426,16 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
@CompileStatic
private static Optional<String> findPrimaryClassName(String javaSrc) {
- List<TypeDeclaration<?>> result = new LinkedList<>()
- CompilationUnit compilationUnit = StaticJavaParser.parse(javaSrc)
-
+ CompilationUnit compilationUnit= StaticJavaParser.parse(javaSrc)
for (TypeDeclaration<?> td : compilationUnit.getTypes()) {
- if (!(td.isTopLevelType() && td.isClassOrInterfaceDeclaration() && td.getModifiers().contains(Modifier.publicModifier()))) continue
-
- if (td.fullyQualifiedName.isPresent()) {
- result << td
- }
- }
-
- String className = null
- if (!result.isEmpty()) {
- Optional<String> optionalClassName = result.get(0).getFullyQualifiedName()
- if (optionalClassName.isPresent()) {
- className = optionalClassName.get()
+ if (td.isPublic()
+ && td.isTopLevelType()
+ && td.isClassOrInterfaceDeclaration()
+ && td.getFullyQualifiedName().isPresent()) {
+ return td.getFullyQualifiedName();
}
}
-
- return Optional.ofNullable(className)
+ return Optional.empty()
}
void compileAsJava(EventObject evt = null) {