You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2017/09/13 12:50:58 UTC
[1/2] groovy git commit: GROOVY-7721: Static type checking fails when
compiling against a Java interface call (closes #599)
Repository: groovy
Updated Branches:
refs/heads/GROOVY_2_6_X d39107bb9 -> 5db125714
GROOVY-7721: Static type checking fails when compiling against a Java interface call (closes #599)
(cherry picked from commit 34df6cf)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/c7774a3a
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/c7774a3a
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/c7774a3a
Branch: refs/heads/GROOVY_2_6_X
Commit: c7774a3a0ba624036312666493c313cc62d21e59
Parents: d39107b
Author: sunlan <su...@apache.org>
Authored: Wed Sep 13 20:20:11 2017 +0800
Committer: sunlan <su...@apache.org>
Committed: Wed Sep 13 20:50:16 2017 +0800
----------------------------------------------------------------------
.../stc/StaticTypeCheckingSupport.java | 11 ++-
src/test/groovy/bugs/Groovy7721Bug.groovy | 80 ++++++++++++++++++++
2 files changed, 89 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/c7774a3a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 98fb157..eb208fe 100644
--- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1149,13 +1149,20 @@ public abstract class StaticTypeCheckingSupport {
private static void removeMethodWithSuperReturnType(List<MethodNode> toBeRemoved, MethodNode one, MethodNode two) {
ClassNode oneRT = one.getReturnType();
ClassNode twoRT = two.getReturnType();
- if (oneRT.isDerivedFrom(twoRT) || oneRT.implementsInterface(twoRT)) {
+ if (isCovariant(oneRT, twoRT)) {
toBeRemoved.add(two);
- } else if (twoRT.isDerivedFrom(oneRT) || twoRT.implementsInterface(oneRT)) {
+ } else if (isCovariant(twoRT, oneRT)) {
toBeRemoved.add(one);
}
}
+ private static boolean isCovariant(ClassNode left, ClassNode right) {
+ if (left.isArray() && right.isArray()) {
+ return isCovariant(left.getComponentType(), right.getComponentType());
+ }
+ return left.isDerivedFrom(right) || left.implementsInterface(right);
+ }
+
private static boolean areOverloadMethodsInSameClass(MethodNode one, MethodNode two) {
return one.getName().equals(two.getName()) && one.getDeclaringClass() == two.getDeclaringClass();
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/c7774a3a/src/test/groovy/bugs/Groovy7721Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/bugs/Groovy7721Bug.groovy b/src/test/groovy/bugs/Groovy7721Bug.groovy
new file mode 100644
index 0000000..f316a2a
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy7721Bug.groovy
@@ -0,0 +1,80 @@
+/*
+ * 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.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit
+
+class Groovy7721Bug extends GroovyTestCase {
+ void testCovariantArrayAtOverriding() {
+ def config = new CompilerConfiguration()
+ config.with {
+ targetDirectory = createTempDir()
+ jointCompilationOptions = [stubDir: createTempDir()]
+ }
+
+ File parentDir = createTempDir()
+ try {
+ def a = new File(parentDir, 'A.java')
+ a.write '''
+ package pack;
+ interface A {
+ Object[] bar();
+ }
+
+ '''
+ def b = new File(parentDir, 'B.java')
+ b.write '''
+ package pack;
+ interface B extends A {
+ @Override
+ String[] bar();
+ }
+ '''
+
+ def c = new File(parentDir, 'C.groovy')
+ c.write '''
+ import groovy.transform.CompileStatic
+
+ @CompileStatic
+ class C {
+ static def bar(pack.B b) {
+ b.bar()
+ }
+ }
+ '''
+ def loader = new GroovyClassLoader(this.class.classLoader)
+ def cu = new JavaAwareCompilationUnit(config, loader)
+ cu.addSources([a, b, c] as File[])
+ cu.compile()
+ } finally {
+ parentDir.deleteDir()
+ config.targetDirectory?.deleteDir()
+ config.jointCompilationOptions.stubDir?.deleteDir()
+ }
+
+ }
+
+ private static File createTempDir() {
+ File.createTempDir("groovyTest${System.currentTimeMillis()}", "")
+ }
+
+}
[2/2] groovy git commit: GROOVY-8300: @AutoFinal (asciidoc doco)
Posted by su...@apache.org.
GROOVY-8300: @AutoFinal (asciidoc doco)
(cherry picked from commit 9ea35d6)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/5db12571
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/5db12571
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/5db12571
Branch: refs/heads/GROOVY_2_6_X
Commit: 5db12571492b064fe4fdde679ee0ff1fc8469616
Parents: c7774a3
Author: paulk <pa...@asert.com.au>
Authored: Wed Sep 13 20:35:27 2017 +0800
Committer: sunlan <su...@apache.org>
Committed: Wed Sep 13 20:50:23 2017 +0800
----------------------------------------------------------------------
src/spec/doc/core-metaprogramming.adoc | 37 ++++++++++++++++
.../CompilerDirectivesASTTransformsTest.groovy | 46 ++++++++++++++++++++
2 files changed, 83 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/5db12571/src/spec/doc/core-metaprogramming.adoc
----------------------------------------------------------------------
diff --git a/src/spec/doc/core-metaprogramming.adoc b/src/spec/doc/core-metaprogramming.adoc
index f2ffdc4..e18784a 100644
--- a/src/spec/doc/core-metaprogramming.adoc
+++ b/src/spec/doc/core-metaprogramming.adoc
@@ -2357,6 +2357,43 @@ The `@PackageScope` annotation is seldom used as part of normal Groovy conventio
for factory methods that should be visible internally within a package or for methods or constructors provided
for testing purposes, or when integrating with third-party libraries which require such visibility conventions.
+[[xform-AutoFinal]]
+===== `@groovy.transform.AutoFinal`
+
+The `@AutoFinal` annotation instructs the compiler to automatically insert the final modifier
+in numerous places within the annotated node. If applied on a method (or constructor), the parameters
+for that method (or constructor) will be marked as final. If applied on a class definition, the same
+treatment will occur for all declared methods and constructors within that class.
+
+It is often considered bad practice to reassign parameters of a method or constructor with its body.
+By adding the final modifier to all parameter declarations you can avoid this practice entirely.
+Some programmers feel that adding final everywhere increases the amount of boilerplate code and makes the
+method signatures somewhat noisy. An alternative might instead be to use a code review process or apply
+a http://codenarc.org[codenarc] http://codenarc.sourceforge.net/codenarc-rules-convention.html#ParameterReassignment[rule]
+to give warnings if that practice is observed but these alternatives might lead to delayed feedback during
+quality checking rather than within the IDE or during compilation. The `@AutoFinal` annotation aims to
+maximise compiler/IDE feedback while retaining succinct code with minimum boilerplate noise.
+
+The following example illustrates applying the annotation at the class level:
+
+[source,groovy]
+----
+include::{projectdir}/src/spec/test/CompilerDirectivesASTTransformsTest.groovy[tags=autofinal_class,indent=0]
+----
+
+In this example, the two parameters for the constructor and the single parameter for
+both the `fullname` and `greeting` methods will be final. Attempts to modify those parameters within the
+constructor or method bodies will be flagged by the compiler.
+
+The following example illustrates applying the annotation at the method level:
+
+[source,groovy]
+----
+include::{projectdir}/src/spec/test/CompilerDirectivesASTTransformsTest.groovy[tags=autofinal_method,indent=0]
+----
+
+Here, the `add` method will have final parameters but the `mult` method will remain unchanged.
+
[[xform-AnnotationCollector]]
===== `@groovy.transform.AnnotationCollector`
http://git-wip-us.apache.org/repos/asf/groovy/blob/5db12571/src/spec/test/CompilerDirectivesASTTransformsTest.groovy
----------------------------------------------------------------------
diff --git a/src/spec/test/CompilerDirectivesASTTransformsTest.groovy b/src/spec/test/CompilerDirectivesASTTransformsTest.groovy
index 29ccd9f..8e72851 100644
--- a/src/spec/test/CompilerDirectivesASTTransformsTest.groovy
+++ b/src/spec/test/CompilerDirectivesASTTransformsTest.groovy
@@ -96,6 +96,52 @@ new MyScript().run()
'''
}
+ void testAutoFinalClass() {
+ assertScript '''
+// tag::autofinal_class[]
+import groovy.transform.AutoFinal
+
+@AutoFinal
+class Person {
+ private String first, last
+
+ Person(String first, String last) {
+ this.first = first
+ this.last = last
+ }
+
+ String fullName(String separator) {
+ "$first$separator$last"
+ }
+
+ String greeting(String salutation) {
+ "$salutation, $first"
+ }
+}
+// end::autofinal_class[]
+def john = new Person('John', 'Smith')
+assert john.fullName(' ') == 'John Smith'
+assert john.greeting('Hello') == 'Hello, John'
+'''
+ }
+
+ void testAutoFinalMethod() {
+ assertScript '''
+import groovy.transform.AutoFinal
+// tag::autofinal_method[]
+class Calc {
+ @AutoFinal
+ int add(int a, int b) { a + b }
+
+ int mult(int a, int b) { a * b }
+}
+// end::autofinal_method[]
+def calc = new Calc()
+assert calc.add(3, 6) == 9
+assert calc.mult(3, 6) == 18
+'''
+ }
+
void testPackageScope() {
assertScript '''import java.lang.reflect.Modifier
// tag::packagescope_property[]