This is an automated email from the ASF dual-hosted git repository. paulk pushed a commit to branch GROOVY_2_5_X in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_2_5_X by this push: new 3555f42 GROOVY-8953: Imported enum causes compilation bug preventing tests from compiling (closes #885) 3555f42 is described below commit 3555f4207a7b9738bc97a479670ad86491847fa8 Author: Paul King <pa...@asert.com.au> AuthorDate: Wed Feb 27 17:49:34 2019 +1000 GROOVY-8953: Imported enum causes compilation bug preventing tests from compiling (closes #885) --- .../org/codehaus/groovy/vmplugin/v5/Java5.java | 14 +++--- src/test/groovy/bugs/Groovy8008Bug.java | 57 +++++++++++++++++----- src/test/groovy/bugs/groovy8953/Enum8953.java | 28 +++++++++++ .../SyntheticParameterAnnotationsBug.groovy | 32 ++++++++++++ 4 files changed, 113 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v5/Java5.java b/src/main/java/org/codehaus/groovy/vmplugin/v5/Java5.java index b745405..44d18ee 100644 --- a/src/main/java/org/codehaus/groovy/vmplugin/v5/Java5.java +++ b/src/main/java/org/codehaus/groovy/vmplugin/v5/Java5.java @@ -450,18 +450,20 @@ public class Java5 implements VMPlugin { Annotation[][] annotations = constructor.getParameterAnnotations(); int diff = parameterCount - annotations.length; if (diff > 0) { - // May happen on JDK8 and below, but we only expect to have to - // add a single element to the front of the array to account - // for the synthetic outer reference - if (diff > 1) { + // May happen on JDK8 and below. We add elements to the front of the array to account for the synthetic params: + // - for an inner class we expect one param to account for the synthetic outer reference + // - for an enum we expect two params to account for the synthetic name and ordinal + if ((!constructor.getDeclaringClass().isEnum() && diff > 1) || diff > 2) { throw new GroovyBugError( "Constructor parameter annotations length [" + annotations.length + "] " + "does not match the parameter length: " + constructor ); } Annotation[][] adjusted = new Annotation[parameterCount][]; - adjusted[0] = EMPTY_ANNOTATION_ARRAY; - System.arraycopy(annotations, 0, adjusted, 1, annotations.length); + for (int i = 0; i < diff; i++) { + adjusted[i] = EMPTY_ANNOTATION_ARRAY; + } + System.arraycopy(annotations, 0, adjusted, diff, annotations.length); return adjusted; } return annotations; diff --git a/src/test/groovy/bugs/Groovy8008Bug.java b/src/test/groovy/bugs/Groovy8008Bug.java index 84c1f86..94974ed 100644 --- a/src/test/groovy/bugs/Groovy8008Bug.java +++ b/src/test/groovy/bugs/Groovy8008Bug.java @@ -47,7 +47,7 @@ public class Groovy8008Bug extends TestCase { Class<Inner> innerClass = Inner.class; Constructor<Inner> ctor = innerClass.getDeclaredConstructor(Groovy8008Bug.class, String.class, Date.class, String.class); - assertEquals(4, ctor.getParameterTypes().length); //Groovy8008Bug,String,Date,String + assertEquals(4, ctor.getParameterTypes().length); // JDK 9 and above correctly report 4 // assertEquals(3, ctor.getParameterAnnotations().length); //[],[@Anno1,@Anno2],[@Anno2] @@ -58,24 +58,57 @@ public class Groovy8008Bug extends TestCase { assertEquals(1, ctors.size()); Parameter[] params = ctors.get(0).getParameters(); + checkOuterRef(params[0], Groovy8008Bug.class); + checkStringWithNoAnnos(params[1]); + checkDateWithTwoAnnos(params[2]); + checkStringWithOneAnno(params[3]); - assertEquals(Groovy8008Bug.class.getName(), params[0].getType().getName()); - assertEquals(0, params[0].getAnnotations().size()); + // do the same again for an inner inner class + Class<Inner.InnerInner> innerInnerClass = Inner.InnerInner.class; + Constructor<Inner.InnerInner> innerCtor = innerInnerClass.getDeclaredConstructor(Groovy8008Bug.Inner.class, String.class, Date.class, String.class); + assertEquals(4, innerCtor.getParameterTypes().length); - assertEquals(String.class.getName(), params[1].getType().getName()); - assertEquals(0, params[1].getAnnotations().size()); + cn = new ClassNode(innerInnerClass); - assertEquals(Date.class.getName(), params[2].getType().getName()); - assertEquals(2, params[2].getAnnotations().size()); - assertEquals(TestAnno1.class.getName(), params[2].getAnnotations().get(0).getClassNode().getName()); - assertEquals(TestAnno2.class.getName(), params[2].getAnnotations().get(1).getClassNode().getName()); + // trigger the call to VMPlugin#configureClassNode(CompileUnit,ClassNode) + ctors = cn.getDeclaredConstructors(); + assertEquals(1, ctors.size()); + + params = ctors.get(0).getParameters(); + checkOuterRef(params[0], Groovy8008Bug.Inner.class); + checkStringWithNoAnnos(params[1]); + checkDateWithTwoAnnos(params[2]); + checkStringWithOneAnno(params[3]); + } + + private void checkOuterRef(Parameter param, Class outerClass) { + assertEquals(outerClass.getName(), param.getType().getName()); + assertEquals(0, param.getAnnotations().size()); + } - assertEquals(String.class.getName(), params[3].getType().getName()); - assertEquals(1, params[3].getAnnotations().size()); - assertEquals(TestAnno2.class.getName(), params[3].getAnnotations().get(0).getClassNode().getName()); + private void checkStringWithOneAnno(Parameter param) { + assertEquals(String.class.getName(), param.getType().getName()); + assertEquals(1, param.getAnnotations().size()); + assertEquals(TestAnno2.class.getName(), param.getAnnotations().get(0).getClassNode().getName()); + } + + private void checkStringWithNoAnnos(Parameter param) { + assertEquals(String.class.getName(), param.getType().getName()); + assertEquals(0, param.getAnnotations().size()); + } + + private void checkDateWithTwoAnnos(Parameter param2) { + assertEquals(Date.class.getName(), param2.getType().getName()); + assertEquals(2, param2.getAnnotations().size()); + assertEquals(TestAnno1.class.getName(), param2.getAnnotations().get(0).getClassNode().getName()); + assertEquals(TestAnno2.class.getName(), param2.getAnnotations().get(1).getClassNode().getName()); } private class Inner { private Inner(String arg1, @TestAnno1 @TestAnno2 Date arg2, @TestAnno2 String arg3) { } + + private class InnerInner { + private InnerInner(String arg1, @TestAnno1 @TestAnno2 Date arg2, @TestAnno2 String arg3) { } + } } } diff --git a/src/test/groovy/bugs/groovy8953/Enum8953.java b/src/test/groovy/bugs/groovy8953/Enum8953.java new file mode 100644 index 0000000..a40a098 --- /dev/null +++ b/src/test/groovy/bugs/groovy8953/Enum8953.java @@ -0,0 +1,28 @@ +/* + * 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.groovy8953; + +public enum Enum8953 { + A("value"); + public String value; + + Enum8953(@Deprecated final String value) { + this.value = value; + } +} diff --git a/src/test/groovy/bugs/groovy8953/SyntheticParameterAnnotationsBug.groovy b/src/test/groovy/bugs/groovy8953/SyntheticParameterAnnotationsBug.groovy new file mode 100644 index 0000000..316e5b9 --- /dev/null +++ b/src/test/groovy/bugs/groovy8953/SyntheticParameterAnnotationsBug.groovy @@ -0,0 +1,32 @@ +/* + * 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.groovy8953 + +class SyntheticParameterAnnotationsBug extends GroovyTestCase { + void testEnumConstructorWithSyntheticParamUsageWithAsmResolvingDisabled() { + assertScript ''' + import org.codehaus.groovy.control.CompilerConfiguration + + def script = "assert groovy.bugs.groovy8953.Enum8953.A.value == 'value'" + def config = new CompilerConfiguration() + config.optimizationOptions.asmResolving = false + new GroovyShell(config).evaluate(script, "bug8953_dummyName.groovy") + ''' + } +}