You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/09/12 06:12:09 UTC
[1/2] groovy git commit: GROOVY-8300: Initial version having no
configuration options (closes #594)
Repository: groovy
Updated Branches:
refs/heads/master 7693721df -> 46df5eb62
GROOVY-8300: Initial version having no configuration options (closes #594)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/37eed47b
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/37eed47b
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/37eed47b
Branch: refs/heads/master
Commit: 37eed47b5f3afaedeff4ac4529d23a489b3517e3
Parents: 4bd92e6
Author: paulk <pa...@asert.com.au>
Authored: Tue Aug 29 10:57:53 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Tue Sep 12 16:10:40 2017 +1000
----------------------------------------------------------------------
src/main/groovy/transform/AutoFinal.java | 75 ++++++++++++++++++
.../transform/AutoFinalASTTransformation.java | 81 ++++++++++++++++++++
.../transform/AutoFinalTransformTest.groovy | 64 ++++++++++++++++
3 files changed, 220 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/37eed47b/src/main/groovy/transform/AutoFinal.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/transform/AutoFinal.java b/src/main/groovy/transform/AutoFinal.java
new file mode 100644
index 0000000..5fb673f
--- /dev/null
+++ b/src/main/groovy/transform/AutoFinal.java
@@ -0,0 +1,75 @@
+/*
+ * 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.transform;
+
+import org.codehaus.groovy.transform.GroovyASTTransformationClass;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to automatically add final to various syntactic structures,
+ * saving you typing of some boilerplate code.
+ * Initially, only method and constructor parameters are supported.
+ * The annotation may be placed on any method or constructor.
+ * It can also be placed at the class level in which case it applies to
+ * all methods and constructors within the class.
+ * <p>
+ * <em>Example usage:</em>
+ * <pre class="groovyTestCase">
+ * {@code @groovy.transform.AutoFinal}
+ * class Person {
+ * final String first, last
+ * Person(String first, String last) {
+ * this.first = first
+ * this.last = last
+ * }
+ * String fullName(boolean reversed = false, String separator = ' ') {
+ * "${reversed ? last : first}$separator${reversed ? first : last}"
+ * }
+ * }
+ *
+ * def js = new Person('John', 'Smith')
+ * assert js.fullName() == 'John Smith'
+ * assert js.fullName(true, ', ') == 'Smith, John'
+ * </pre>
+ * for this case, the constructor for the <code>Person</code> class will be
+ * equivalent to the following code:
+ * <pre>
+ * Person(final String first, final String last) {
+ * //...
+ * }
+ * </pre>
+ * And after normal default parameter processing takes place, the following overloaded methods will exist:
+ * <pre>
+ * String fullName(final boolean reversed, final String separator) { ... }
+ * String fullName(final boolean reversed) { fullName(reversed, ' ') }
+ * String fullName() { fullName(false) }
+ * </pre>
+ *
+ * @since 2.5.0
+ */
+@java.lang.annotation.Documented
+@Retention(RetentionPolicy.SOURCE)
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
+@GroovyASTTransformationClass("org.codehaus.groovy.transform.AutoFinalASTTransformation")
+public @interface AutoFinal {
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/37eed47b/src/main/org/codehaus/groovy/transform/AutoFinalASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/AutoFinalASTTransformation.java b/src/main/org/codehaus/groovy/transform/AutoFinalASTTransformation.java
new file mode 100644
index 0000000..36fc7b1
--- /dev/null
+++ b/src/main/org/codehaus/groovy/transform/AutoFinalASTTransformation.java
@@ -0,0 +1,81 @@
+/*
+ * 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 org.codehaus.groovy.transform;
+
+import groovy.transform.AutoFinal;
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.ConstructorNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.control.CompilePhase;
+import org.codehaus.groovy.control.SourceUnit;
+
+import java.lang.reflect.Modifier;
+
+import static org.codehaus.groovy.ast.ClassHelper.make;
+
+/**
+ * Handles generation of code for the {@code @}AutoFinal annotation.
+ */
+@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
+public class AutoFinalASTTransformation extends AbstractASTTransformation {
+
+ private static final Class MY_CLASS = AutoFinal.class;
+ private static final ClassNode MY_TYPE = make(MY_CLASS);
+ private static final String MY_TYPE_NAME = "@" + MY_TYPE.getNameWithoutPackage();
+
+ public void visit(ASTNode[] nodes, SourceUnit source) {
+ init(nodes, source);
+ AnnotatedNode candidate = (AnnotatedNode) nodes[1];
+ AnnotationNode node = (AnnotationNode) nodes[0];
+ if (!MY_TYPE.equals(node.getClassNode())) return;
+
+ if (candidate instanceof ClassNode) {
+ processClass((ClassNode) candidate);
+ } else if (candidate instanceof MethodNode) {
+ // handles constructors and methods
+ processConstructorOrMethod((MethodNode) candidate);
+ }
+ }
+
+ private void processClass(ClassNode cNode) {
+ if (cNode.isInterface()) {
+ addError("Error processing interface '" + cNode.getName() +
+ "'. " + MY_TYPE_NAME + " only allowed for classes.", cNode);
+ return;
+ }
+ for (ConstructorNode cn : cNode.getDeclaredConstructors()) {
+ processConstructorOrMethod(cn);
+ }
+ for (MethodNode mn : cNode.getAllDeclaredMethods()) {
+ processConstructorOrMethod(mn);
+ }
+ }
+
+ private void processConstructorOrMethod(MethodNode node) {
+ if (node.isSynthetic()) return;
+ Parameter[] origParams = node.getParameters();
+ for (Parameter p : origParams) {
+ p.setModifiers(p.getModifiers() | Modifier.FINAL);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/37eed47b/src/test/org/codehaus/groovy/transform/AutoFinalTransformTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/transform/AutoFinalTransformTest.groovy b/src/test/org/codehaus/groovy/transform/AutoFinalTransformTest.groovy
new file mode 100644
index 0000000..339daa4
--- /dev/null
+++ b/src/test/org/codehaus/groovy/transform/AutoFinalTransformTest.groovy
@@ -0,0 +1,64 @@
+/*
+ * 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 org.codehaus.groovy.transform
+
+import gls.CompilableTestSupport
+
+/**
+ * Tests for the {@code @AutoFinal} AST transform.
+ */
+class AutoFinalTransformTest extends CompilableTestSupport {
+
+ void testAutoFinalOnClass() {
+ // use ASTTest here since final modifier isn't put into bytecode so not available via reflection
+ assertScript '''
+ import groovy.transform.AutoFinal
+ import groovy.transform.ASTTest
+ import static org.codehaus.groovy.control.CompilePhase.SEMANTIC_ANALYSIS
+ import static java.lang.reflect.Modifier.isFinal
+
+ @ASTTest(phase=SEMANTIC_ANALYSIS, value = {
+ assert node.methods.size() == 1
+ node.methods[0].with {
+ assert it.name == 'fullName'
+ assert it.parameters.every{ p -> isFinal(p.modifiers) }
+ }
+ assert node.constructors.size() == 1
+ node.constructors[0].with {
+ assert it.parameters.every{ p -> isFinal(p.modifiers) }
+ }
+ })
+ @AutoFinal
+ class Person {
+ final String first, last
+ Person(String first, String last) {
+ this.first = first
+ this.last = last
+ }
+ String fullName(boolean reversed = false, String separator = ' ') {
+ "${reversed ? last : first}$separator${reversed ? first : last}"
+ }
+ }
+
+ def js = new Person('John', 'Smith')
+ assert js.fullName() == 'John Smith'
+ assert js.fullName(true, ', ') == 'Smith, John'
+ '''
+ }
+}
[2/2] groovy git commit: Merge branch 'groovy8300'
Posted by pa...@apache.org.
Merge branch 'groovy8300'
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/46df5eb6
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/46df5eb6
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/46df5eb6
Branch: refs/heads/master
Commit: 46df5eb629b03bf81bb2483d86538283dd159330
Parents: 7693721 37eed47
Author: paulk <pa...@asert.com.au>
Authored: Tue Sep 12 16:11:20 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Tue Sep 12 16:11:20 2017 +1000
----------------------------------------------------------------------
src/main/groovy/transform/AutoFinal.java | 75 ++++++++++++++++++
.../transform/AutoFinalASTTransformation.java | 81 ++++++++++++++++++++
.../transform/AutoFinalTransformTest.groovy | 64 ++++++++++++++++
3 files changed, 220 insertions(+)
----------------------------------------------------------------------