/*
* Copyright 2009-2017 the original author or authors.
*
* Licensed 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.eclipse.jdt.groovy.core.tests.basic;
import static org.eclipse.jdt.core.tests.util.GroovyUtils.isAtLeastGroovy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ImportNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.jdt.groovy.internal.compiler.ast.AliasImportReference;
import org.codehaus.jdt.groovy.internal.compiler.ast.EventListener;
import org.codehaus.jdt.groovy.internal.compiler.ast.GroovyClassScope;
import org.codehaus.jdt.groovy.internal.compiler.ast.GroovyCompilationUnitDeclaration;
import org.codehaus.jdt.groovy.internal.compiler.ast.JDTClassNode;
import org.codehaus.jdt.groovy.internal.compiler.ast.JDTResolver;
import org.eclipse.jdt.core.tests.util.GroovyUtils;
import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.junit.Ignore;
import org.junit.Test;
public final class GroovySimpleTests extends GroovyCompilerTestSuite {
public GroovySimpleTests(long level) {
super(level);
}
@Test
public void testClosureSyntax() {
runNegativeTest(new String[] {
"Foo.groovy",
"class A {\n"+
" A(closure) {\n"+
" closure()\n"+
" }\n"+
"}\n"+
"abc = {println 'abc'\n"+
"}\n"+
"new A({\n"+
" abc()\n"+
"}) //works properly\n"+
"new A() { \n"+
" abc()\n"+
"} // throw error: unexpected token: abc at line: 13, column: 3\n"
},
"----------\n" +
"1. ERROR in Foo.groovy (at line 12)\n" +
"\tabc()\n" +
"\t^\n" +
"Groovy:unexpected token: abc @ line 12, column 5.\n" +
"----------\n");
}
@Test
public void testGreclipse1521_pre() {
assumeTrue(isAtLeastGroovy(20));
runConformTest(new String[] {
"Foo.groovy",
"enum Color { R,G,B;}\n"
});
}
@Test
public void testGreclipse719() {
runNegativeTest(new String[] {
"MyDomainClass.groovy",
"int anInt = 10;\n"+
"def Method[] methodArray = anInt.class.methods;\n"+
"println methodArray.name;"
},
"----------\n" +
"1. ERROR in MyDomainClass.groovy (at line 2)\n" +
"\tdef Method[] methodArray = anInt.class.methods;\n" +
"\t ^^^^^^^^\n" +
"Groovy:unable to resolve class Method[] \n" +
"----------\n");
}
@Test
public void testGreclipse719_2() {
runNegativeTest(new String[] {
"MyDomainClass.groovy",
"int anInt = 10;\n"+
"def Method[][] methodMethodArray = anInt.class.methods;\n"+
"println methodArray.name;"
},
"----------\n" +
"1. ERROR in MyDomainClass.groovy (at line 2)\n" +
"\tdef Method[][] methodMethodArray = anInt.class.methods;\n" +
"\t ^^^^^^^^^^\n" +
"Groovy:unable to resolve class Method[][] \n" +
"----------\n");
}
@Test
public void testDuplicateClassesUnnecessaryExceptions() {
runNegativeTest(new String[] {
"A.groovy",
"class Foo {}\n"+
"class Foo {}"
},
"----------\n" +
"1. ERROR in A.groovy (at line 2)\n" +
"\tclass Foo {}\n" +
"\t^" + (GroovyUtils.isAtLeastGroovy(20) ? "^^^^^^^^^^^" : "") + "\n" +
"Groovy:Invalid duplicate class definition of class Foo : The source A.groovy contains at least two definitions of the class Foo.\n" +
"----------\n" +
"2. ERROR in A.groovy (at line 2)\n" +
"\tclass Foo {}\n" +
"\t ^^^\n" +
"The type Foo is already defined\n" +
"----------\n");
}
@Test
public void testStaticProperty() {
runConformTest(new String[] {
"A.groovy",
"class Super {" +
" def static getSql() { return 'abc'; }\n" +
"}\n"+
"class Sub extends Super {\n" +
" def static m() {\n" +
" sql.charAt(0)\n"+
" }" +
"}\n"
});
}
@Test @Ignore
public void testClash_GRE1076() {
runConformTest(new String[] {
"com/foo/Bar/config.groovy",
"package com.foo.Bar\n"+
"print 'abc'\n",
"com/foo/Bar.java",
"package com.foo;\n"+
"class Bar {}\n"
},
"abc");
}
@Test @Ignore
public void testClash_GRE1076_2() {
runConformTest(new String[] {
"com/foo/Bar.java",
"package com.foo;\n"+
"public class Bar { \n"+
" public static void main(String[] argv) {\n"+
" System.out.println(\"def\");\n"+
" }\n"+
"}\n",
"com/foo/Bar/config.groovy",
"package com.foo.Bar\n"+
"print 'abc'\n"
},
"def");
}
@Test
public void testUnreachable_1047() {
runConformTest(new String[] {
"MyException.java",
"class MyException extends Exception {\n"+
" private static final long serialVersionUID = 1L;\n"+
"}",
"CanThrowException.groovy",
"\n"+
"public interface CanThrowException {\n"+
" void thisCanThrowException() throws MyException\n"+
"}\n",
"ShouldCatchException.java",
"\n"+
"class ShouldCatchException {\n"+
" private CanThrowException thing;\n"+
" \n"+
" public void doIt() {\n"+
" try {\n"+
" thing.thisCanThrowException();\n"+
" } catch( MyException e ) {\n"+
" System.out.println(\"Did we catch it?\");\n"+
" }\n"+
" }\n"+
"}\n"
});
}
@Test
public void testUnreachable_1047_2() {
runConformTest(new String[] {
"MyException.java",
"class MyException extends Exception {\n"+
" private static final long serialVersionUID = 1L;\n"+
"}",
"CanThrowException.groovy",
"\n"+
"public class CanThrowException {\n"+
" public CanThrowException() throws MyException {\n"+
" throw new MyException();\n"+
" }\n"+
"}\n",
"ShouldCatchException.java",
"\n"+
"class ShouldCatchException {\n"+
" \n"+
" public void doIt() {\n"+
" try {\n"+
" new CanThrowException();\n"+
" } catch( MyException e ) {\n"+
" System.out.println(\"Did we catch it?\");\n"+
" }\n"+
" }\n"+
"}\n"
});
}
/**
* This test is looking at what happens when a valid type is compiled ahead of two problem types (problematic
* since they both declare the same class). Although the first file gets through resolution OK, re-resolution
* is attempted because the SourceUnit isn't tagged as having succeeded that phase - the exception thrown
* for the real problem jumps over the tagging process.
*/
@Test
public void testDuplicateClassesUnnecessaryExceptions_GRE796() {
runNegativeTest(new String[] {
"spring/resources.groovy",
"foo = {}\n",
"A.groovy",
"class Foo {}\n",
"Foo.groovy",
"class Foo {}",
},
"----------\n" +
"1. ERROR in Foo.groovy (at line 1)\n" +
"\tclass Foo {}\n" +
"\t ^"+(GroovyUtils.isAtLeastGroovy(20)?"^^^^^^^^^^":"")+"\n" +
"Groovy:Invalid duplicate class definition of class Foo : The sources Foo.groovy and A.groovy "+
(GroovyUtils.isAtLeastGroovy(22) ? "each contain a class with the name" : "are containing both a class of the name") + " Foo.\n" +
"----------\n" +
"2. ERROR in Foo.groovy (at line 1)\n" +
"\tclass Foo {}\n" +
"\t ^^^\n" +
"The type Foo is already defined\n" +
"----------\n");
}
@Test
public void testDuplicateClassesUnnecessaryExceptions_GRE796_2() {
runNegativeTest(new String[] {
"spring/resources.groovy",
"foo = {}\n",
"a/Foo.groovy",
"package a\n"+
"class Foo {}\n" +
"class Foo {}",
},
"----------\n" +
"1. ERROR in a\\Foo.groovy (at line 3)\n" +
"\tclass Foo {}\n" +
"\t^"+(GroovyUtils.isAtLeastGroovy(20)?"^^^^^^^^^^^":"")+"\n" +
"Groovy:Invalid duplicate class definition of class a.Foo : The source a"+File.separator+"Foo.groovy contains at least two definitions of the class a.Foo.\n" +
"----------\n" +
"2. ERROR in a\\Foo.groovy (at line 3)\n" +
"\tclass Foo {}\n" +
"\t ^^^\n" +
"The type Foo is already defined\n" +
"----------\n");
}
@Test
public void testGroovyColon_GRE801() {
runNegativeTest(new String[] {
"A.groovy",
"httpClientControl.demand.generalConnection(1..1) = {->\n"+
"currHttp\n"+
"} \n"
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\thttpClientControl.demand.generalConnection(1..1) = {->\n" +
"\t ^\n" +
"Groovy:\"httpClientControl.demand.generalConnection((1..1))\" is a method call expression, but it should be a variable expression at line: 1 column: 50. File: A.groovy @ line 1, column 50.\n" +
"----------\n");
}
@Test
public void testStaticOuter_GRE944() {
runNegativeTest(new String[] {
"A.groovy",
"static class A {\n"+
" public static void main(String[]argv) {print 'abc';}\n"+
"}\n",
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\tstatic class A {\n" +
"\t ^\n" +
"Groovy:The class \'A\' has an incorrect modifier static.\n" +
"----------\n");
}
@Test
public void testCrashRatherThanError_GRE986() {
runNegativeTest(new String[] {
"A.groovy",
"hello \\u\n"+
"class Foo {}\n"
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\thello \\u\n" +
"\t ^\n" +
"Groovy:Did not find four digit hex character code. line: 1 col:7 @ line 1, column 7.\n" +
"----------\n");
}
@Test
public void testAmbiguous_GRE945_gu() {
runConformTest(new String[] {
"Code.groovy",
"import bug.factory.*\n"+
"class Code {\n"+
" static Factory fact = new Factory()\n"+
" public static void main(String[]argv) {\n"+
" fact.foo()\n"+
" }\n"+
"}\n",
"Factory.groovy",
"package bug.factory\n"+
"class Factory { static foo() { print 'abc'}}\n",
},
"abc");
}
@Test
public void testAmbiguous_GRE945_jl() {
runConformTest(new String[] {
"Code.groovy",
"import bug.factory.*\n"+
"class Code {\n"+
" static StringBuffer fact = new StringBuffer()\n"+
" public static void main(String[]argv) {\n"+
" print fact.foo()\n"+
" }\n"+
"}\n",
"StringBuffer.groovy",
"package bug.factory\n"+
"class StringBuffer { static String foo() { return 'abc'}}\n",
},
"abc");
}
@Test
public void testAmbiguous_GRE945_bothFromSource() {
runConformTest(new String[] {
"Code.groovy",
"import a.*\n"+
"import b.*\n"+
"class Code {\n"+
" static A fact = new A()\n"+
" public static void main(String[]argv) {\n"+
" print fact.foo()\n"+
" }\n"+
"}\n",
"a/A.groovy",
"package a\n"+
"class A { static String foo() { return 'abc'}}\n",
"b/A.groovy",
"package b\n"+
"class A { static String foo() { return 'def'}}\n",
},
"abc");
}
@Test
public void testAmbiguous_GRE945_bothFromSource_2() {
runConformTest(new String[] {
"Code.groovy",
"import b.*\n"+
"import a.*\n"+
"class Code {\n"+
" static A fact = new A()\n"+
" public static void main(String[]argv) {\n"+
" print fact.foo()\n"+
" }\n"+
"}\n",
"a/A.groovy",
"package a\n"+
"class A { static String foo() { return 'abc'}}\n",
"b/A.groovy",
"package b\n"+
"class A { static String foo() { return 'def'}}\n",
},
"def");
}
@Test
public void testAmbiguous_GRE945_bothFromSource_3() {
runConformTest(new String[] {
"Code.groovy",
"import b.*\n"+
"import a.*\n"+
"class Code {\n"+
" static Process fact = new Process()\n"+
" public static void main(String[]argv) {\n"+
" print fact.foo()\n"+
" }\n"+
"}\n",
"a/Process.groovy",
"package a\n"+
"class Process { static String foo() { return 'abc'}}\n",
"b/Process.groovy",
"package b\n"+
"class Process { static String foo() { return 'def'}}\n",
},
"def");
}
@Test
public void testAmbiguous_GRE945_ju() {
runConformTest(new String[] {
"Code.groovy",
"import bug.factory.*\n"+
"class Code {\n"+
" static List fact = new List()\n"+
" public static void main(String[]argv) {\n"+
" fact.foo()\n"+
" }\n"+
"}\n",
"List.groovy",
"package bug.factory\n"+
"class List { static foo() { print 'abc'}}\n",
},
"abc");
}
@Test
public void testAmbiguous_GRE945_jn() {
runConformTest(new String[] {
"Code.groovy",
"import bug.factory.*\n"+
"class Code {\n"+
" static Socket fact = new Socket()\n"+
" public static void main(String[]argv) {\n"+
" fact.foo()\n"+
" }\n"+
"}\n",
"Socket.groovy",
"package bug.factory\n"+
"class Socket { static foo() { print 'abc'}}\n",
},
"abc");
}
@Test
public void testAmbiguous_GRE945_gl() {
runConformTest(new String[] {
"Code.groovy",
"import bug.factory.*\n"+
"class Code {\n"+
" static Tuple fact = new Tuple()\n"+
" public static void main(String[]argv) {\n"+
" fact.foo()\n"+
" }\n"+
"}\n",
"Tuple.groovy",
"package bug.factory\n"+
"class Tuple { static foo() { print 'abc'}}\n",
},
"abc");
}
@Test
public void testAmbiguous_GRE945_ji() {
runConformTest(new String[] {
"Code.groovy",
"import bug.factory.*\n"+
"class Code {\n"+
" static Serializable fact = new Serializable()\n"+
" public static void main(String[]argv) {\n"+
" fact.foo()\n"+
" }\n"+
"}\n",
"Serializable.groovy",
"package bug.factory\n"+
"class Serializable { static foo() { print 'abc'}}\n",
},
"abc");
}
@Test
public void testStaticOuter_GRE944_2() {
runNegativeTest(new String[] {
"B.java",
"public class B {\n"+
" public static void main(String[] argv) {\n" +
" new A.C().foo();\n" +
" }\n" +
"}\n",
"A.groovy",
"static class A {\n"+
" static class C {\n"+
" public void foo() {print 'abcd';}\n"+
" }\n"+
"}\n",
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\tstatic class A {\n" +
"\t ^\n" +
"Groovy:The class \'A\' has an incorrect modifier static.\n" +
"----------\n");
}
@Test
public void testEnumStatic_GRE974() {
runConformTest(new String[] {
"A.groovy",
"package be.flow\n"+
"\n"+
"enum C1{\n"+
" TEST_C1\n"+
"} \n"+
"\n"+
"class A {\n"+
" public enum C2{\n"+
" TEST_C2\n"+
" }\n"+
"}",
"B.groovy",
"package be.flow\n"+
"\n"+
"import static be.flow.C1.TEST_C1;\n"+
"import static be.flow.A.C2.*;\n"+
"\n"+
"class B {\n"+
" \n"+
" B(){\n"+
" super(TEST_C2)\n"+
" }\n"+
" \n"+
" void doIt(){\n"+
" println(be.flow.C1.TEST_C1);\n"+
" println(be.flow.A.C2.TEST_C2);\n"+
" println(TEST_C2);\n"+
" }\n"+
" \n"+
"}",
"D.groovy",
"package be.flow\n"+
"\n"+
"import static be.flow.C1.TEST_C1;\n"+
"import static be.flow.A.C2.*;\n"+
"\n"+
"class D {\n"+
" \n"+
" static void doIt(){\n"+
" println(be.flow.C1.TEST_C1);\n"+
" println(be.flow.A.C2.TEST_C2);\n"+
" println(TEST_C2);\n"+
" }\n"+
" \n"+
"}"
});
}
@Test
public void testVarargs_GRE925() {
runConformTest(new String[] {
"Test.java",
"class Test {\n"+
" void method(String[] x) {}\n"+
" public static void main(String []argv) {}\n"+
"}",
"SubTest.groovy",
"class SubTest extends Test {\n"+
" void method(String[] x) { super.method(x); }\n"+
"}"
});
}
@Test
public void testPrimitiveLikeTypeNames_GRE891() {
runConformTest(new String[] {
"Foo.java",
"public class Foo {\n"+
"public static void main(String[] args) {\n"+
" Z[][] zs = new Z().zzz();\n"+
" System.out.println(\"works\");\n"+
" }\n"+
"}",
"Z.groovy",
"class Z {\n"+
" Z[][] zzz() { null }\n"+
"}\n"},"works");
// return type is a single char type (not in package and not primitive)
assertEquals("[[LZ;",getReturnTypeOfMethod("Z.groovy","zzz"));
}
@Test
public void testPrimitiveLikeTypeNames_GRE891_2() {
runConformTest(new String[] {
"Foo.java",
"public class Foo {\n"+
"public static void main(String[] args) {\n"+
" int[][] zs = new Z().zzz();\n"+
" System.out.println(\"works\");\n"+
" }\n"+
"}",
"Z.groovy",
"class Z {\n"+
" int[][] zzz() { null }\n"+
"}\n"},"works");
// return type is a primitive
assertEquals("[[I",getReturnTypeOfMethod("Z.groovy","zzz"));
}
@Test
public void testPrimitiveLikeTypeNames_GRE891_3() {
runConformTest(new String[] {
"Foo.java",
"public class Foo {\n"+
"public static void main(String[] args) {\n"+
" java.lang.String[][] zs = new Z().zzz();\n"+
" System.out.println(\"works\");\n"+
" }\n"+
"}",
"Z.groovy",
"class Z {\n"+
" java.lang.String[][] zzz() { null }\n"+
"}\n"},"works");
// return type is a qualified java built in type
assertEquals("[[Ljava.lang.String;",getReturnTypeOfMethod("Z.groovy","zzz"));
}
@Test
public void testAnonymousClasses_GE1531() {
runNegativeTest(new String[] {
"Foo.groovy",
"class Foo {\n"+
" def foo () {\n"+
" new java.lang.Runnable () {}//<--quick fix here\n"+
" }\n"+
"}"},
"----------\n" +
"1. ERROR in Foo.groovy (at line 3)\n" +
"\tnew java.lang.Runnable () {}//<--quick fix here\n" +
"\t ^^^^^^^^^^^^^^^^^^^\n" +
"Groovy:Can\'t have an abstract method in a non-abstract class. The class \'Foo$1\' must be declared abstract or the method \'void run()\' must be implemented.\n" +
"----------\n");
// return type is a qualified java built in type
ModuleNode mn = getModuleNode("Foo$1.class");
System.out.println(mn);
}
@Test
public void testPrimitiveLikeTypeNames_GRE891_4() {
runConformTest(new String[] {
"pkg/Foo.java",
"package pkg;\n"+
"public class Foo {\n"+
"public static void main(String[] args) {\n"+
" pkg.H[][] zs = new Z().zzz();\n"+
" System.out.println(\"works\");\n"+
" }\n"+
"}",
"Y.groovy",
"package pkg\n"+
"class H {}\n",
"Z.groovy",
"package pkg\n"+
"class Z {\n"+
" H[][] zzz() { null }\n"+
"}\n"},"works");
// return type is a single char groovy type from a package
assertEquals("[[Lpkg.H;",getReturnTypeOfMethod("Z.groovy","zzz"));
}
@Test
public void testPrimitiveLikeTypeNames_GRE891_5() {
runConformTest(new String[] {
"pkg/Foo.java",
"package pkg;\n"+
"public class Foo {\n"+
"public static void main(String[] args) {\n"+
" H[][] zs = new Z().zzz();\n"+
" System.out.println(\"works\");\n"+
" }\n"+
"}",
"Y.java",
"package pkg;\n"+
"class H {}\n",
"Z.groovy",
"package pkg;\n"+
"class Z {\n"+
" H[][] zzz() { null }\n"+
"}\n"},"works");
// return type is a single char java type from a package
assertEquals("[[Lpkg.H;",getReturnTypeOfMethod("Z.groovy","zzz"));
}
@Test
public void testOverridingFinalMethod() {
runNegativeTest(new String[] {
"Base.groovy",
"class Base {\n"+
" final getFinalProperty() { 1 }\n"+
"}\n"+
"class Child extends Base {\n"+
" def finalProperty = 32 \n"+
" public static void main(String []argv) {\n"+
" print new Child().getFinalProperty();\n"+
" }\n"+
"}"
},
"----------\n" +
"1. ERROR in Base.groovy (at line 4)\n" +
"\tclass Child extends Base {\n" +
"\t ^^^^^\n" +
"Cannot override the final method from Base\n" +
"----------\n");
}
@Test
public void testMixedModeInnerProperties_GRE597() {
runConformTest(new String[] {
"groovy/JoinGroovy.groovy",
"package groovy\n"+
"\n"+
"class JointGroovy {\n"+
"StaticInner property\n"+
"\n"+
" static class StaticInner {\n"+
" NonStaticInner property2\n"+
"\n"+
" class NonStaticInner {\n"+
" Closure property3 = {}\n"+
" }\n"+
" }\n"+
"}",
"groovy/JointJava.java",
"package groovy;\n"+
"\n"+
"import groovy.lang.Closure;\n"+
"\n"+
"public class JointJava {\n"+
" public void method() {\n"+
" Closure closure = new JointGroovy().getProperty().getProperty2().getProperty3();\n"+
" }\n"+
"}"});
}
@Test
public void testMixedModeInnerProperties2_GRE597() {
runConformTest(new String[] {
"groovy/JoinGroovy.groovy",
"package groovy\n"+
"\n"+
"class JointGroovy {\n"+
"StaticInner property\n"+
"\n"+
" }\n"+
// now the inner is not an inner (like the previous test) but the property3 still is
" class StaticInner {\n"+
" NonStaticInner property2\n"+
"\n"+
" class NonStaticInner {\n"+
" Closure property3 = {}\n"+
" }\n"+
"}",
"groovy/JointJava.java",
"package groovy;\n"+
"\n"+
"import groovy.lang.Closure;\n"+
"\n"+
"public class JointJava {\n"+
" public void method() {\n"+
" Closure closure = new JointGroovy().getProperty().getProperty2().getProperty3();\n"+
" }\n"+
"}"});
}
@Test
public void testStaticVariableInScript() {
runNegativeTest(new String[] {
"Script.groovy",
"enum Move { ROCK, PAPER, SCISSORS }\n"+
"\n"+
"final static BEATS = [\n"+
" [Move.ROCK, Move.SCISSORS],\n"+
" [Move.PAPER, Move.ROCK],\n"+
" [Move.SCISSORS, Move.PAPER]\n"+
"].asImmutable()"
},
"----------\n" +
"1. ERROR in Script.groovy (at line 3)\n" +
"\tfinal static BEATS = [\n" +
"\t ^^^^^\n" +
"Groovy:Modifier 'static' not allowed here.\n" +
"----------\n");
}
// WMTW: What makes this work: the groovy compiler is delegated to for .groovy files
@Test
public void testStandaloneGroovyFile() {
runConformTest(new String[] {
"p/X.groovy",
"package p;\n" +
"public class X {\n" +
" public static void main(String[] argv) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
},"success");
}
@Test
public void testRecursion_GR531() {
runNegativeTest(new String[] {
"XXX.groovy",
"class XXX extends XXX {\n" +
"}\n",
},"----------\n" +
"1. ERROR in XXX.groovy (at line 1)\n" +
"\tclass XXX extends XXX {\n" +
"\t ^^^\n" +
"Groovy:Cyclic inheritance involving XXX in class XXX\n" +
"----------\n" +
"2. ERROR in XXX.groovy (at line 1)\n" +
"\tclass XXX extends XXX {\n" +
"\t ^^^\n" +
"Cycle detected: the type XXX cannot extend/implement itself or one of its own member types\n" +
"----------\n");
}
@Test
public void testRecursion_GR531_2() {
runNegativeTest(new String[] {
"XXX.groovy",
"class XXX extends XXX {\n" +
" public static void main(String[] argv) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
},"----------\n" +
"1. ERROR in XXX.groovy (at line 1)\n" +
"\tclass XXX extends XXX {\n" +
"\t ^^^\n" +
"Groovy:Cyclic inheritance involving XXX in class XXX\n" +
"----------\n" +
"2. ERROR in XXX.groovy (at line 1)\n" +
"\tclass XXX extends XXX {\n" +
"\t ^^^\n" +
"Cycle detected: the type XXX cannot extend/implement itself or one of its own member types\n" +
"----------\n");
}
@Test
public void testRecursion_GR531_3() {
runNegativeTest(new String[] {
"XXX.groovy",
"class XXX extends YYY {\n" +
" public static void main(String[] argv) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
"YYY.groovy",
"class YYY extends XXX {\n" +
" public static void main(String[] argv) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n"
},"----------\n" +
"1. ERROR in XXX.groovy (at line 1)\n" +
"\tclass XXX extends YYY {\n" +
"\t ^^^\n" +
"The hierarchy of the type XXX is inconsistent\n" +
"----------\n" +
"----------\n" +
"1. ERROR in YYY.groovy (at line 1)\n" +
"\tclass YYY extends XXX {\n" +
"\t ^^^\n" +
"Groovy:Cyclic inheritance involving YYY in class YYY\n" +
"----------\n" +
"2. ERROR in YYY.groovy (at line 1)\n" +
"\tclass YYY extends XXX {\n" +
"\t ^^^\n" +
"Cycle detected: a cycle exists in the type hierarchy between YYY and XXX\n" +
"----------\n");
}
@Test
public void testRecursion_GR531_4() {
runNegativeTest(new String[] {
"XXX.groovy",
"interface XXX extends XXX {\n" +
"}\n",
},"----------\n" +
"1. ERROR in XXX.groovy (at line 1)\n" +
"\tinterface XXX extends XXX {\n" +
"\t ^^^\n" +
"Groovy:Cyclic inheritance involving XXX in interface XXX\n" +
"----------\n" +
"2. ERROR in XXX.groovy (at line 1)\n" +
"\tinterface XXX extends XXX {\n" +
"\t ^^^^\n" +
"Cycle detected: the type XXX cannot extend/implement itself or one of its own member types\n" +
"----------\n");
}
/**
* The groovy object method augmentation (in GroovyClassScope) should only apply to types directly implementing GroovyObject, rather than
* adding them all the way down the hierarchy. This mirrors what happens in the compiler.
*/
/**
* First a class extending another. The superclass gets augmented but not the subclass.
*/
@Test
public void testClassHierarchiesAndGroovyObjectMethods() {
try {
GroovyClassScope.debugListener = new EventListener("augment");
runConformTest(new String[] {
"Foo.groovy",
"class Foo {\n"+
" static main(args) { print 'abc'} \n"+
"}\n" +
"class Two extends Foo {\n" +
" public void m() {\n"+
" Object o = getMetaClass();\n"+
" }\n"+
"}\n",
},"abc");
assertEventCount(1,GroovyClassScope.debugListener);
assertEvent("augment: type Foo having GroovyObject methods added",GroovyClassScope.debugListener);
System.err.println(GroovyClassScope.debugListener.toString());
} finally {
GroovyClassScope.debugListener=null;
}
}
/**
* Now a class implementing an interface. The subclass gets augmented because the superclass did not.
*/
@Test
public void testClassHierarchiesAndGroovyObjectMethods2() {
try {
GroovyClassScope.debugListener = new EventListener("augment");
runConformTest(new String[] {
"Foo.groovy",
"class Foo implements One {\n" +
" public void m() {\n"+
" Object o = getMetaClass();\n"+
" }\n"+
" static main(args) { print 'abc'} \n"+
"}\n"+
"interface One {\n"+
"}\n",
},"abc");
assertEventCount(1,GroovyClassScope.debugListener);
assertEvent("augment: type Foo having GroovyObject methods added",GroovyClassScope.debugListener);
System.err.println(GroovyClassScope.debugListener.toString());
} finally {
GroovyClassScope.debugListener=null;
}
}
/**
* Now a class extending a java type which extends a base groovy class. Super groovy type should get them.
*
* This looks odd to me, not sure why Foo and One both get the methods when One inherits them through Foo -
* perhaps the java type in the middle makes a difference. Anyway by augmenting both of these we
* are actually doing the same as groovyc, and that is the main thing.
*/
@Test
public void testClassHierarchiesAndGroovyObjectMethods3() {
try {
GroovyClassScope.debugListener = new EventListener();
runConformTest(new String[] {
"Foo.groovy",
"class Foo extends Two {\n" +
" public void m() {\n"+
" Object o = getMetaClass();\n"+
" }\n"+
" static main(args) { print 'abc'} \n"+
"}\n"+
"class One {\n"+
"}\n",
"Two.java",
"class Two extends One {}\n",
},"abc");
assertEventCount(2,GroovyClassScope.debugListener);
assertEvent("augment: type One having GroovyObject methods added",GroovyClassScope.debugListener);
assertEvent("augment: type Foo having GroovyObject methods added",GroovyClassScope.debugListener);
} finally {
GroovyClassScope.debugListener=null;
}
}
@Test
public void testStandaloneGroovyFile2() {
runConformTest(new String[] {
"p/X.groovy",
"package p;\n" +
"public class X {\n" +
// " public static void main(String[] args) {\n"+
" static main(args) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
},"success");
checkGCUDeclaration("X.groovy",
"package p;\n" +
"public class X {\n" +
" public X() {\n" +
" }\n" +
// for: public static void main(String[] args) {
//" public static void main(public String... args) {\n" +
// for: static main(args) {
" public static void main(public java.lang.String... args) {\n" +
" }\n" +
"}\n"
);
}
@Test
public void testParentIsObject_GRE528() {
runConformTest(new String[] {
"p/X.groovy",
"package p;\n" +
"public class X {\n" +
" static main(args) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
},"success");
checkGCUDeclaration("X.groovy",
"package p;\n" +
"public class X {\n" +
" public X() {\n" +
" }\n" +
" public static void main(public java.lang.String... args) {\n" +
" }\n" +
"}\n"
);
}
@Test
public void testInnerTypes() {
runConformTest(new String[] {
"p/X.groovy",
"package p;\n" +
"public class X {\n" +
" class Inner {}\n"+
" static main(args) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
},"success");
checkGCUDeclaration("X.groovy",
"package p;\n" +
"public class X {\n" +
" public class Inner {\n" +
" public Inner() {\n"+
" }\n"+
" }\n"+
" public X() {\n" +
" }\n" +
" public static void main(public java.lang.String... args) {\n" +
" }\n" +
"}\n"
);
}
@Test
public void testBrokenPackage() {
runNegativeTest(new String[] {
"Foo.groovy",
"package \n"+
"class Name { }\n"},
"----------\n" +
"1. ERROR in Foo.groovy (at line 1)\n" +
"\tpackage \n" +
"\t ^\n" +
"Groovy:Invalid package specification @ line 1, column 1.\n" +
"----------\n");
}
@Test // GROOVY-4219
public void testGRE637() {
assumeTrue(isAtLeastGroovy(22));
runConformTest(new String[] {
"de/brazzy/nikki/Texts.java",
"package de.brazzy.nikki;\n"+
"\n"+
"public final class Texts { \n"+
" public static class Image {\n"+
" public static final String ORDERED_BY_FILENAME = \"image.sortedby.filename\";\n"+
" public static final String ORDERED_BY_TIME = \"image.sortedby.time\";\n"+
"}}\n",
"de/brazzy/nikki/model/Image.groovy",
"package de.brazzy.nikki.model;\n"+
"\n"+
"class Image implements Serializable{\n"+
" def fileName\n"+
" def time\n"+
"}\n",
"de/brazzy/nikki/model/ImageSortField.groovy",
"package de.brazzy.nikki.model\n"+
"\n"+
"import de.brazzy.nikki.Texts\n"+
"import de.brazzy.nikki.model.Image\n"+
"\n"+
"enum ImageSortField {\n"+
" FILENAME(field: Image.metaClass.fileName, name: Texts.Image.ORDERED_BY_FILENAME),\n"+
" TIME(field: Image.metaClass.time, name: Texts.Image.ORDERED_BY_TIME)\n"+
"\n"+
" def field\n"+
" def name\n"+
"\n"+
" public String toString(){\n"+
" name\n"+
" }\n"+
"}\n"
});
}
@Test
public void testOverriding_GRE440() {
runConformTest(new String[] {
"Foo.groovy",
"class Foo { \n"+
" static void main(args) {}\n"+
"}",
"Goo.java",
"class Goo extends Foo { \n"+
" public static void main(String[] argv) {}\n"+
"}",
});
//checkGCUDeclaration("Foo.groovy", "yyy");
}
@Test
public void testOverriding_GRE440_2() {
runConformTest(new String[] {
"Foo.java",
"class Foo { \n"+
" void main(String... ss) {}\n"+
"}",
"Goo.java",
"class Goo extends Foo { \n"+
" void main(String[] ss) {}\n"+
"}",
});
//checkGCUDeclaration("Foo.java", "yyy");
}
@Test
public void testAliasing_GRE473() {
runConformTest(new String[] {
"Foo.groovy",
"import java.util.regex.Pattern as JavaPattern\n"+
"class Pattern {JavaPattern javaPattern}\n"+
"def p = new Pattern(javaPattern:~/\\d+/)\n"+
"assert \"123\" ==~ p.javaPattern\n"+
"print 'success '\n"+
"print '['+p.class.package+']['+JavaPattern.class.package.name+']'\n"},
"success [null][java.util.regex]");
}
@Test
public void testAliasing_GRE473_2() {
runNegativeTest(new String[] {
"Foo.groovy",
"import java.util.regex.Pattern\n"+
"class Pattern {Pattern javaPattern}\n"+
"def p = new Pattern(javaPattern:~/\\d+/)\n"+
"assert \"123\" ==~ p.javaPattern\n"+
"print 'success'\n"},
"----------\n" +
"1. ERROR in Foo.groovy (at line 1)\n" +
"\timport java.util.regex.Pattern\n" +
"\t ^^^^^^^\n" +
"The import java.util.regex.Pattern conflicts with a type defined in the same file\n" +
"----------\n");
}
@Test
public void testBrokenPackage2() {
runNegativeTest(new String[] {
"Foo.groovy",
"package ;\n"+
"class Name { }\n"},
"----------\n" +
"1. ERROR in Foo.groovy (at line 1)\n" +
"\tpackage ;\n" +
"\t ^\n" +
"Groovy:Invalid package specification @ line 1, column 1.\n" +
"----------\n");
}
// does the second error now get reported after the package problem
@Test
public void testBrokenPackage3() {
runNegativeTest(new String[] {
"Foo.groovy",
"package ;\n"+
"class Name { \n" +
" asdf\n"+
"}\n"},
"----------\n" +
"1. ERROR in Foo.groovy (at line 1)\n" +
"\tpackage ;\n" +
"\t ^\n" +
"Groovy:Invalid package specification @ line 1, column 1.\n" +
"----------\n" +
"2. ERROR in Foo.groovy (at line 3)\n" +
"\tasdf\n" +
"\t^\n" +
"Groovy:unexpected token: asdf @ line 3, column 3.\n" +
"----------\n");
}
@Test
public void testEnumPositions_GRE1072() {
assumeTrue(isAtLeastGroovy(20));
runConformTest(new String[] {
"X.groovy",
"enum Color {\n" +
" /** hello */\n"+
" RED,\n"+
" GREEN,\n"+
" BLUE\n"+
"}\n",
});
GroovyCompilationUnitDeclaration decl = getCUDeclFor("X.groovy");
FieldDeclaration fDecl = grabField(decl, "RED");
assertEquals("RED sourceStart>sourceEnd:30>32 declSourceStart>declSourceEnd:15>32 modifiersSourceStart=30 endPart1Position:30", stringifyFieldDecl(fDecl));
fDecl = grabField(decl, "GREEN");
assertEquals("GREEN sourceStart>sourceEnd:37>41 declSourceStart>declSourceEnd:37>41 modifiersSourceStart=37 endPart1Position:37", stringifyFieldDecl(fDecl));
fDecl = grabField(decl, "BLUE");
assertEquals("BLUE sourceStart>sourceEnd:46>49 declSourceStart>declSourceEnd:46>49 modifiersSourceStart=46 endPart1Position:46", stringifyFieldDecl(fDecl));
}
@Test
public void testEnumValues_GRE1071() {
runConformTest(new String[] {
"X.groovy",
"enum H {\n"+
" RED,\n"+
" BLUE\n"+
"}"},"");
assertEquals("[LH;",getReturnTypeOfMethod("X.groovy", "values"));
}
@Test
public void testAbstractCovariance_GRE272() {
runNegativeTest(new String[] {
"A.java",
"public class A {}",
"AA.java",
"public class AA extends A{}",
"I.java",
"public interface I { A getA();}",
"Impl.java",
"public class Impl implements I { public AA getA() {return null;}}",
"GImpl.groovy",
"class GImpl extends Impl {}"
},"");
}
// If GroovyFoo is processed *before* FooBase then the MethodVerifier15
// hasn't had a chance to run on FooBase and create the synthetic bridge method
@Test
public void testAbstractCovariance_GRE272_2() {
runNegativeTest(new String[] {
"test/Bar.java",
"package test;\n"+
"public class Bar extends BarBase {}",
"test/BarBase.java",
"package test;\n"+
"abstract public class BarBase {}",
"test/GroovyFoo.groovy",
"package test;\n"+
"class GroovyFoo extends FooBase {}",
"test/FooBase.java",
"package test;\n"+
"public class FooBase implements IFoo { public Bar foo() {return null;}}",
"test/IFoo.java",
"package test;\n"+
"public interface IFoo { BarBase foo();}",
},"");
}
@Test
public void testAbstractCovariance_GRE272_3() {
runNegativeTest(new String[] {
"test/IFoo.java",
"package test;\n"+
"public interface IFoo { BarBase foo();}",
"test/GroovyFoo.groovy",
"package test;\n"+
"class GroovyFoo extends FooBase {}",
"test/FooBase.java",
"package test;\n"+
"public class FooBase implements IFoo { public Bar foo() {return null;}}",
"test/BarBase.java",
"package test;\n"+
"abstract public class BarBase {}",
"test/Bar.java",
"package test;\n"+
"public class Bar extends BarBase {}",
},"");
}
@Test
public void testAbstractCovariance_GRE272_4() {
runNegativeTest(new String[] {
"test/IFoo.java",
"package test;\n"+
"public interface IFoo { BarBase foo();}",
"test/FooBase.java",
"package test;\n"+
"public class FooBase implements IFoo { public Bar foo() {return null;}}",
"test/BarBase.java",
"package test;\n"+
"abstract public class BarBase {}",
"test/Bar.java",
"package test;\n"+
"public class Bar extends BarBase {}",
"test/GroovyFoo.groovy",
"package test;\n"+
"class GroovyFoo extends FooBase {}",
},"");
}
@Test
public void testIncorrectReturnType_GRE292() {
runNegativeTest(new String[] {
"Voidy.groovy",
"public class VoidReturnTestCase {\n"+
"\n"+
" void returnSomething() { \n"+
" return true && false \n" +
" }\n"+
"\n"+
"}\n"},
"----------\n" +
"1. ERROR in Voidy.groovy (at line 4)\n" +
"\treturn true && false \n" +
"\t^^^^^^^^^^^^^^^^^^^^\n" +
"Groovy:Cannot use return statement with an expression on a method that returns void\n" +
"----------\n");
}
@Test
public void testIncorrectReturnType_GRE292_3() {
runNegativeTest(new String[] {
"Voidy.groovy",
"public class VoidReturnTestCase {\n"+
"\n"+
" void returnSomething() { \n"+
" return true\n" +
" }\n"+
"\n"+
"}\n"},
"----------\n" +
"1. ERROR in Voidy.groovy (at line 4)\n" +
"\treturn true\n" +
"\t^^^^^^^^^^^\n" +
"Groovy:Cannot use return statement with an expression on a method that returns void\n" +
"----------\n");
}
@Test
public void testIncorrectReturnType_GRE292_2() {
runNegativeTest(new String[] {
"Voidy.groovy",
"public class VoidReturnTestCase {\n"+
"\n"+
" void returnSomething() { return true }\n"+
"\n"+
"}\n"},
"----------\n"+
"1. ERROR in Voidy.groovy (at line 3)\n" +
"\tvoid returnSomething() { return true }\n" +
"\t ^^^^^^^^^^^\n" +
"Groovy:Cannot use return statement with an expression on a method that returns void\n" +
"----------\n");
}
@Test
public void testIncorrectReturnType_GRE292_4() {
runNegativeTest(new String[] {
"Voidy.groovy",
"public class VoidReturnTestCase {\n"+
"\n"+
" void returnSomething() { return 375+26 }\n"+
"\n"+
"}\n"},
"----------\n" +
"1. ERROR in Voidy.groovy (at line 3)\n" +
"\tvoid returnSomething() { return 375+26 }\n" +
"\t ^^^^^^^^^^^^^\n" +
"Groovy:Cannot use return statement with an expression on a method that returns void\n" +
"----------\n");
}
@Test
public void testMissingTypesForGeneratedBindingsGivesNPE_GRE273() {
runNegativeTest(new String[] {
"X.groovy",
"import java.util.Map\n"+
"import org.andrill.coretools.data.edit.Command\n"+
"import org.andrill.coretools.data.edit.EditableProperty\n"+
"import org.andrill.coretools.data.Model\n"+
"import org.andrill.coretools.data.ModelCollection\n"+
"import org.andrill.coretools.data.edit.commands.CompositeCommand\n"+
"\n"+
"class GProperty implements EditableProperty {\n"+
"def source\n"+
"String name\n"+
"String widgetType\n"+
"Map widgetProperties = [:]\n"+
"Map constraints = [:]\n"+
"def validators = []\n"+
"Command command\n"+
"\n"+
"String getValue() {\n"+
"if (source instanceof Model) { return source.modelData[name] } else { return (source.\"$name\" as String) }\n"+
"}\n"+
"\n"+
"boolean isValid(String newValue) {\n"+
"try {\n"+
"return validators.inject(true) { prev, cur -> prev && cur.call([newValue, source]) }\n"+
"} catch (e) { return false }\n"+
"}\n"+
"\n"+
"Command getCommand(String newValue) {\n"+
"if (constraints?.linkTo && source instanceof Model) {\n"+
"def value = source.\"$name\"\n"+
"def links = source.collection.models.findAll { it.class == source.class && it?.\"${constraints.linkTo}\" == value }\n"+
"if (links) {\n"+
"def commands = []\n"+
"commands << new GCommand(source: source, prop: name, value: newValue)\n"+
"links.each { commands << new GCommand(source: it, prop: constraints.linkTo, value: newValue) }\n"+
"return new CompositeCommand(\"Change $name\", (commands as Command[]))\n"+
"} else { return new GCommand(source: source, prop: name, value: newValue) }\n"+
"} else { return new GCommand(source: source, prop: name, value: newValue) }\n"+
"}\n"+
"}\n"
},
"----------\n" +
"1. ERROR in X.groovy (at line 2)\n" +
"\timport org.andrill.coretools.data.edit.Command\n" +
"\t ^^^^^^^\n" +
"Groovy:unable to resolve class org.andrill.coretools.data.edit.Command\n" +
"----------\n" +
"2. ERROR in X.groovy (at line 3)\n" +
"\timport org.andrill.coretools.data.edit.EditableProperty\n" +
"\t ^^^^^^^^^^^^^^^^\n" +
"Groovy:unable to resolve class org.andrill.coretools.data.edit.EditableProperty\n" +
"----------\n" +
"3. ERROR in X.groovy (at line 4)\n" +
"\timport org.andrill.coretools.data.Model\n" +
"\t ^^^^^\n" +
"Groovy:unable to resolve class org.andrill.coretools.data.Model\n" +
"----------\n" +
"4. ERROR in X.groovy (at line 5)\n" +
"\timport org.andrill.coretools.data.ModelCollection\n" +
"\t ^^^^^^^^^^^^^^^\n" +
"Groovy:unable to resolve class org.andrill.coretools.data.ModelCollection\n" +
"----------\n" +
"5. ERROR in X.groovy (at line 6)\n" +
"\timport org.andrill.coretools.data.edit.commands.CompositeCommand\n" +
"\t ^^^^^^^^^^^^^^^^\n" +
"Groovy:unable to resolve class org.andrill.coretools.data.edit.commands.CompositeCommand\n" +
"----------\n" +
"6. ERROR in X.groovy (at line 8)\n" +
"\tclass GProperty implements EditableProperty {\n" +
"\t ^^^^^^^^^\n" +
"Groovy:You are not allowed to implement the class \'org.andrill.coretools.data.edit.EditableProperty\', use extends instead.\n" +
"----------\n" +
"7. WARNING in X.groovy (at line 12)\n" +
"\tMap widgetProperties = [:]\n" +
"\t^^^\n" +
"Map is a raw type. References to generic type Map<K,V> should be parameterized\n" +
"----------\n" +
"8. WARNING in X.groovy (at line 13)\n" +
"\tMap constraints = [:]\n" +
"\t^^^\n" +
"Map is a raw type. References to generic type Map<K,V> should be parameterized\n" +
"----------\n" +
// "9. ERROR in X.groovy (at line 15)\n" +
// "\tCommand command\n" +
// "\t^^^^^^^\n" +
// "Groovy:unable to resolve class org.andrill.coretools.data.edit.Command \n" +
// "----------\n" +
"9. ERROR in X.groovy (at line 33)\n" +
"\tcommands << new GCommand(source: source, prop: name, value: newValue)\n" +
"\t ^^^^^^^^\n" +
"Groovy:unable to resolve class GCommand \n" +
"----------\n" +
"10. ERROR in X.groovy (at line 34)\n" +
"\tlinks.each { commands << new GCommand(source: it, prop: constraints.linkTo, value: newValue) }\n" +
"\t ^^^^^^^^\n" +
"Groovy:unable to resolve class GCommand \n" +
"----------\n" +
"11. ERROR in X.groovy (at line 36)\n" +
"\t} else { return new GCommand(source: source, prop: name, value: newValue) }\n" +
"\t ^^^^^^^^\n" +
"Groovy:unable to resolve class GCommand \n" +
"----------\n" +
"12. ERROR in X.groovy (at line 37)\n" +
"\t} else { return new GCommand(source: source, prop: name, value: newValue) }\n" +
"\t ^^^^^^^^\n" +
"Groovy:unable to resolve class GCommand \n" +
"----------\n");
}
@Test
public void testMissingTypesForGeneratedBindingsGivesNPE_GRE273_2() {
runNegativeTest(new String[] {
"A.groovy",
"class A {\n"+
" String s;"+
" String getS(String foo) { return null;}\n"+
"}"
},"");
}
@Test
public void testAbstractClass_GRE274() {
runNegativeTest(new String[] {
"p/Foo.groovy",
"class Foo {\n" +
" public static void main(String[] argv) {\n"+
" new C();\n"+
" }\n"+
"}\n",
"p/C.java",
"package p;\n" +
"public abstract class C {\n" +
"}\n",
},
"----------\n" +
"1. ERROR in p\\Foo.groovy (at line 3)\n" +
"\tnew C();\n" +
"\t ^\n" +
"Groovy:unable to resolve class C \n" +
"----------\n");
}
@Test
public void testAbstractClass_GRE274_2() {
runNegativeTest(new String[] {
"p/Foo.groovy",
"class Foo {\n" +
" public static void main(String[] argv) {\n"+
" new Wibble();\n"+
" }\n"+
"}\n",
"Wibble.groovy",
"//@SuppressWarnings(\"cast\")\n"+
"public class Wibble implements Comparable<String> {\n" +
"}\n",
},
"----------\n" +
"1. ERROR in Wibble.groovy (at line 2)\n" +
"\tpublic class Wibble implements Comparable<String> {\n" +
"\t ^^^^^^\n" +
"Groovy:Can\'t have an abstract method in a non-abstract class. The class \'Wibble\' must be declared abstract or the method \'int compareTo(java.lang.Object)\' must be implemented.\n" +
"----------\n");
}
@Test
public void testConstructorsForEnumWrong_GRE285() {
runNegativeTest(new String[] {
"TestEnum.groovy",
"enum TestEnum {\n"+
"\n"+
"VALUE1(1, 'foo'),\n"+
"VALUE2(2)\n"+
"\n"+
"private final int _value\n"+
"private final String _description\n"+
"\n"+
"private TestEnum(int value, String description = null) {\n"+
" _value = value\n"+
" _description = description\n"+
"}\n"+
"\n"+
"String getDescription() { _description }\n"+
"\n"+
"int getValue() { _value }\n"+
"}"
},"");
}
@Test @Ignore
public void testCrashingOnBadCode_GRE290() {
runNegativeTest(new String[] {
"Moo.groovy",
"package com.omxgroup.scripting;\n"+
"\n"+
"public class Moo {\n"+
"public static def moo() { println this.class }\n"+
"}\n"
},
"----------\n" +
"1. ERROR in Moo.groovy (at line 4)\n" +
" public static def moo() { println this.class }\n" +
" ^\n" +
"Groovy:class is declared in a dynamic context, but you tried to access it from a static context.\n" +
"----------\n" +
"2. ERROR in Moo.groovy (at line 4)\n" +
" public static def moo() { println this.class }\n" +
" ^\n" +
"Groovy:Non-static variable \'this\' cannot be referenced from the static method moo.\n" +
"----------\n");
}
@Test
public void testCrashingOnBadCode_GRE290_2() {
runNegativeTest(new String[] {
"Moo.groovy",
"public class Moo {\n"+
"\n"+
"public Moo processMoo(final moo) {\n"+
"final moo = processMoo(moo)\n"+
"return moo\n"+
"}\n"+
"}\n"
},
"----------\n" +
"1. ERROR in Moo.groovy (at line 4)\n" +
"\tfinal moo = processMoo(moo)\n" +
"\t ^^^\n" +
"Groovy:The current scope already contains a variable of the name moo\n" +
"----------\n"
);
}
// 'this' by itself isn't an error
@Test
public void testCrashingOnBadCode_GRE290_3() {
runNegativeTest(new String[] {
"Moo.groovy",
"package com.omxgroup.scripting;\n"+
"\n"+
"public class Moo {\n"+
"public static def moo() { println this }\n"+
"}\n"
},
"");
}
@Test
public void testCrashingOnBadCode_GRE290_4() {
runNegativeTest(new String[] {
"p/X.groovy",
"words: [].each { final item ->\n" +
" break words\n"+
" }\n"
},"----------\n" +
"1. ERROR in p\\X.groovy (at line 2)\n" +
"\tbreak words\n" +
"\t^^^^^^^^^^^\n" +
"Groovy:the break statement with named label is only allowed inside loops\n" +
"----------\n");
}
@Test
public void testNPE_GRE291() {
runNegativeTest(new String[] {
"ContinueTestCase.groovy",
"public class ContinueTestCase {\n" +
"\n" +
" public ContinueTestCase() {\n" +
" continue;\n" +
" }\n" +
"}\n" },
"----------\n" +
"1. ERROR in ContinueTestCase.groovy (at line 4)\n" +
"\tcontinue;\n" +
"\t^^^^^^^^\n" +
"Groovy:the continue statement is only allowed inside loops\n" +
"----------\n");
}
@Test
public void testMissingContext_GRE308() {
runNegativeTest(new String[] {
"DibDabs.groovy",
" def run(n) {\n"+
"\n"+
" OtherGroovy.iterate (3) {\n"+
" print it*2\n"+
" } \n"+
"// NOT RECORDED AGAINST THIS FILE??\n"+
" int i "},
"----------\n" +
"1. ERROR in DibDabs.groovy (at line 7)\n" +
"\tint i \n" +
"\t ^\n" +
"Groovy:expecting \'}\', found \'\' @ line 7, column 17.\n" +
"----------\n");
}
// FIXASC less than ideal underlining for error location
@Test
public void testMissingContext_GRE308_2() {
runNegativeTest(new String[] {
"DibDabs.groovy",
" def run(n) {\n"+
"\n"+
" OtherGroovy.iterate (3) {\n"+
" print it*2\n"+
" } \n"+
"// NOT RECORDED AGAINST THIS FILE??\n"+
" int i \n"},
"----------\n" +
"1. ERROR in DibDabs.groovy (at line 7)\n" +
"\tint i \n" +
"\n" +
"\t ^\n" +
"Groovy:expecting \'}\', found \'\' @ line 7, column 18.\n" +
"----------\n");
}
// a valid script, no '.' after session2
@Test
public void testInvalidScripts_GRE323_1() {
runNegativeTest(new String[] {
"Two.groovy",
"def moo(closure) {\n" +
" closure();\n" +
"}\n" +
"\n" +
"moo {\n" +
" final session2 = null\n" +
" \n" +
" // Define scenarios\n" +
" def secBoardRep = session2\n" +
" def x\n" +
"}\n"
},"");
}
@Test
public void testInvalidScripts_GRE323_1b() {
runConformTest(new String[] {
"Two.groovy",
"def moo(closure) {\n" +
" closure();\n" +
"}\n" +
"\n" +
"moo {\n" +
" final session2 = null\n" +
" \n" +
" // Define scenarios\n" +
" def secBoardRep = session2\n" +
" def x\n" +
"}\n"
},"");
}
// '.' added, command line gives:
// One.groovy: 10: expecting '}', found 'x' @ line 10, column 7.
// def x
// ^
@Test
public void testInvalidScripts_GRE323_2() {
// command expression syntax now allows this but it looks weird as
runConformTest(new String[] {
"One.groovy",
"def moo(closure) {\n" +
" closure();\n" +
"}\n" +
"\n" +
"moo {\n" +
" final session2 = null\n" +
" \n" +
" // Define scenarios\n" +
" def secBoardRep = session2.\n" +
" def x\n" +
"}\n"
});
}
// removed surrounding method
@Test
public void testInvalidScripts_GRE323_3() {
runNegativeTest(new String[] {
"Three.groovy",
"def moo(closure) {\n" +
" closure();\n" +
"}\n" +
"\n" +
" final session2 = null\n" +
" \n" +
" // Define scenarios\n" +
" def secBoardRep = session2\n" +
" def x\n"
},"");
}
@Test
public void testInvalidScripts_GRE323_3b() {
runConformTest(new String[] {
"Three.groovy",
"def moo(closure) {\n" +
" closure();\n" +
"}\n" +
"\n" +
" final session2 = null\n" +
" \n" +
" // Define scenarios\n" +
" def secBoardRep = session2\n" +
" def x\n"
},"");
}
// no assignment for session2
@Test
public void testInvalidScripts_GRE323_4() {
runNegativeTest(new String[] {
"Four.groovy",
"def moo(closure) {\n" +
" closure();\n" +
"}\n" +
"\n" +
"moo {\n" +
" final session2 = null\n" +
" \n" +
" // Define scenarios\n" +
" session2.\n" +
" def x\n"+
"}\n"
},"");
}
@Test
public void testInvalidScripts_GRE323_4b() {
runConformTest(new String[] {
"Run.java",
"public class Run {\n"+
" public static void main(String[]argv) {\n"+
" try {\n"+
" Four.main(null);\n"+
" } catch (Throwable t) {\n"+
" System.out.println(t.getMessage());\n"+
" }\n"+
"}\n"+
"}",
"Four.groovy",
"def moo(closure) {\n" +
" closure();\n" +
"}\n" +
"\n" +
"moo {\n" +
" final session2 = null\n" +
" \n" +
" // Define scenarios\n" +
" session2.\n" +
" def x\n"+
"}\n"
},"No such property: x for class: Four");
// actual exception:
// "[ERR]:groovy.lang.MissingPropertyException: No such property: x for class: Four\n"+
// "\tat org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:49)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:49)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:241)\n"+
// "\tat Four$_run_closure1.doCall(Four.groovy:9)\n"+
// "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n"+
// "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n"+
// "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n"+
// "\tat java.lang.reflect.Method.invoke(Method.java:585)\n"+
// "\tat org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)\n"+
// "\tat groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234)\n"+
// "\tat org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)\n"+
// "\tat groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:880)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:143)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:151)\n"+
// "\tat Four$_run_closure1.doCall(Four.groovy)\n"+
// "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n"+
// "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n"+
// "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n"+
// "\tat java.lang.reflect.Method.invoke(Method.java:585)\n"+
// "\tat org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)\n"+
// "\tat groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234)\n"+
// "\tat org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)\n"+
// "\tat groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:880)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:121)\n"+
// "\tat Four.moo(Four.groovy:2)\n"+
// "\tat Four$moo.callCurrent(Unknown Source)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:44)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:143)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:151)\n"+
// "\tat Four.run(Four.groovy:5)\n"+
// "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n"+
// "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n"+
// "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n"+
// "\tat java.lang.reflect.Method.invoke(Method.java:585)\n"+
// "\tat org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)\n"+
// "\tat groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234)\n"+
// "\tat groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1049)\n"+
// "\tat groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:880)\n"+
// "\tat org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:745)\n"+
// "\tat org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:728)\n"+
// "\tat org.codehaus.groovy.runtime.InvokerHelper.runScript(InvokerHelper.java:383)\n"+
// "\tat org.codehaus.groovy.runtime.InvokerHelper$runScript.call(Unknown Source)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)\n"+
// "\tat org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:129)\n"+
// "\tat Four.main(Four.groovy)\n"+
// "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n"+
// "\tat sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)\n"+
// "\tat sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)\n"+
// "\tat java.lang.reflect.Method.invoke(Method.java:585)\n"+
// "\tat \n"
}
@Test
public void testInvalidScripts_GRE323_5() {
runNegativeTest(new String[] {
"Five.groovy",
"def moo(closure) {\n" +
" closure();\n" +
"}\n" +
"\n" +
"moo {\n" +
" final session2 = [\"def\": { println \"DEF\" }]\n" +
" \n" +
" final x = 1\n"+
" // Define scenarios\n" +
" session2.\n" +
" def x\n"+
"}\n"
},"");
}
@Test
public void testInvalidScripts_GRE323_5b() {
runConformTest(new String[] {
"Five.groovy",
"def moo(closure) {\n" +
" closure();\n" +
"}\n" +
"\n" +
"moo {\n" +
" final session2 = [\"def\": { println \"DEF\" }]\n" +
" \n" +
" final x = 1\n"+
" // Define scenarios\n" +
" session2.\n" +
" def x\n"+
"}\n"
},"DEF");
}
@Test
public void testInvalidScripts_GRE323_6() {
runConformTest(new String[] {
"Six.groovy",
"def moo(closure) {\n" +
" closure();\n" +
"}\n" +
"\n" +
"moo {\n" +
" final session2 = [\"def\": { println \"DEF\" }]\n" +
" \n" +
" final x = 1\n"+
" // Define scenarios\n" +
" final y = session2.def x\n" +
"}\n"
},"DEF");
}
@Test
public void testBridgeMethods_GRE336() {
runNegativeTest(new String[] {
"my/example/EnumBooleanMap.java",
"package my.example;\n"+
"\n"+
"import java.util.EnumMap;\n"+
"\n"+
"@SuppressWarnings(\"serial\")\n"+
"public class EnumBooleanMap<E extends Enum<E>> extends EnumMap<E, Boolean> {\n"+
" \n"+
" public EnumBooleanMap(Class<E> keyType) {\n"+
" super(keyType);\n"+
" }\n"+
"\n"+
" public EnumBooleanMap(EnumBooleanMap<E> m) {\n"+
" super(m);\n"+
" }\n"+
"\n"+
" @Override\n"+
" public Boolean get(Object key) {\n"+
" Boolean value = super.get(key);\n"+
" return value != null ? value : false;\n"+
" }\n"+
"}\n"
},"");
}
@Test
public void testInnerTypeReferencing_GRE339() {
runConformTest(new String[] {
"Script.groovy",
"class Script {\n"+
" public static void main(String[] argv) {\n"+
" print Outer.Inner.VAR\n"+
" }\n"+
"}",
"Outer.java",
"public class Outer {\n"+
" static class Inner {\n"+
" static String VAR = \"value\";\n"+
" }\n"+
" }\n"},
"value");
}
// interface
@Test
public void testInnerTypeReferencing_GRE339_2() {
runConformTest(new String[] {
"Script.groovy",
"class Script {\n"+
" public static void main(String[] argv) {\n"+
" print Outer.Inner.VAR\n"+
" }\n"+
"}",
"Outer.java",
"public interface Outer {\n"+
" interface Inner {\n"+
" static String VAR = \"value\";\n"+
" }\n"+
" }\n"},
"value");
}
// pure script
@Test
public void testInnerTypeReferencing_GRE339_3() {
runConformTest(new String[] {
"script.groovy",
"print Outer.Inner.VAR\n",
"Outer.java",
"public interface Outer {\n"+
" interface Inner {\n"+
" static String VAR = \"value\";\n"+
" }\n"+
" }\n"},
"value");
}
@Test
public void testStaticProperties_GRE364() {
runConformTest(new String[] {
"Foo.groovy",
"public class Foo { static String fubar }\n",
"Bar.java",
"public class Bar {\n"+
" String fubar = Foo.getFubar();\n"+
" }\n"},
"");
}
@Test
public void testStaticProperties_GRE364_2() {
runConformTest(new String[] {
"Bar.java",
"public class Bar {\n"+
" String fubar = Foo.getFubar();\n"+
" }\n",
"Foo.groovy",
"public class Foo { static String fubar }\n"},
"");
}
@Test
public void testTransientMethod_GRE370() {
runConformTest(new String[] {
"Foo.groovy",
"public class Foo {\n"+
" public transient void foo() {}\n"+
"}\n"},
"");
}
@Test
public void testNotSeriousEnough_GRE396() {
runNegativeTest(new String[] {
"TrivialBugTest.groovy",
"package org.sjb.sjblib.cmdline;\n"+
"public class TrivialBugTest {\n"+
" void func2() {\n"+
" tb = new TrivialBug()\n"+
" }\n"+
"}\n",
"TrivialBug.groovy",
"package org.sjb.sjblib.cmdline;\n"+
"public class TrivialBug {\n"+
" void func() {\n"+
" return 5\n"+
" }\n"+
"}\n",},
"----------\n" +
"1. ERROR in TrivialBug.groovy (at line 4)\n" +
"\treturn 5\n" +
"\t^^^^^^^^\n" +
"Groovy:Cannot use return statement with an expression on a method that returns void\n" +
"----------\n"
);
}
@Test
public void testNotSeriousEnough_GRE396_2() {
runNegativeTest(new String[] {
"TrivialBug.groovy",
"package org.sjb.sjblib.cmdline;\n"+
"public class TrivialBug {\n"+
" void func() {\n"+
" return 5\n"+
" }\n"+
"}\n",
"TrivialBugTest.groovy",
"package org.sjb.sjblib.cmdline;\n"+
"public class TrivialBugTest {\n"+
" void func2() {\n"+
" tb = new TrivialBug()\n"+
" }\n"+
"}\n",},
"----------\n" +
"1. ERROR in TrivialBug.groovy (at line 4)\n" +
"\treturn 5\n" +
"\t^^^^^^^^\n" +
"Groovy:Cannot use return statement with an expression on a method that returns void\n" +
"----------\n"
);
}
@Test
public void testStarImports_GRE421() {
runConformTest(new String[] {
"Wibble.groovy",
"import a.b.c.*;\n"+
"class Wibble {\n"+
" Process process = new Process()\n"+
" public static void main(String[] argv) { print new Wibble().process.class}\n"+
"}\n",
"a/b/c/Process.java",
"package a.b.c;\n"+
"public class Process {}\n"},
"class a.b.c.Process");
}
// The getter for 'description' implements the interface
@Test
public void testImplementingAnInterfaceViaProperty() {
runConformTest(new String[] {
"a/b/c/C.groovy",
"package a.b.c;\n" +
"import p.q.r.I;\n"+
"public class C implements I {\n" +
" String description;\n"+
" public static void main(String[] argv) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
"p/q/r/I.groovy",
"package p.q.r;\n" +
"public interface I {\n" +
" String getDescription();\n"+
"}\n",
},"success");
}
// Referencing from a groovy to a java type where the reference is through a member, not the hierarchy
@Test
public void testReferencingOtherTypesInSamePackage() {
runConformTest(new String[] {
"a/b/c/C.groovy",
"package a.b.c;\n" +
"public class C {\n" +
" D description;\n"+
" public static void main(String[] argv) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
"a/b/c/D.java",
"package a.b.c;\n" +
"public class D {\n" +
" String getDescription() { return null;}\n"+
"}\n",
},"success");
}
// Ensures that the Point2D.Double reference is resolved in the context of X and not Y (if Y is used then the import isn't found)
@Test
public void testMemberTypeResolution() {
runConformTest(new String[] {
"p/X.groovy",
"package p;\n" +
"import java.awt.geom.Point2D;\n"+
"public class X {\n" +
" public void foo() {\n"+
" Object o = new Point2D.Double(p.x(),p.y());\n"+
" }\n"+
" public static void main(String[] argv) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
"p/Y.groovy",
"package p;\n" +
"public class Y {\n" +
" public void foo() {\n"+
" }\n"+
" public static void main(String[] argv) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
},"success");
}
@Test
public void testFailureWhilstAttemptingToReportError() {
runNegativeTest(new String[] {
"T.groovy",
"public class T{\n"+
" def x () {\n"+
" this \"\"\n"+
" }\n"+
"}\n"
},"----------\n" +
"1. ERROR in T.groovy (at line 3)\n" +
"\tthis \"\"\n" +
"\t ^"+(GroovyUtils.isAtLeastGroovy(20)?"^":"")+"\n" +
"Groovy:Constructor call must be the first statement in a constructor. at line: 3 column: 8. File: T.groovy @ line 3, column 8.\n" +
"----------\n");
}
@Test
public void testExtendingInterface1() {
runNegativeTest(new String[] {
"p/X.groovy",
"package p;\n" +
"public class X extends I {\n" +
"}\n",
"p/I.groovy",
"package p\n"+
"interface I {}",
},
"----------\n" +
"1. ERROR in p\\X.groovy (at line 2)\n" +
"\tpublic class X extends I {\n" +
"\t ^\n" +
"Groovy:You are not allowed to extend the interface \'p.I\', use implements instead.\n" +
"----------\n");
}
@Test
public void testProtectedType() {
runConformTest(new String[] {
"p/Y.groovy",
"package p;\n" +
"class Y {\n" +
" public static void main(String[]argv) {\n"+
" new X().main(argv);\n"+
" }\n"+
"}\n",
"p/X.groovy",
"package p;\n" +
"protected class X {\n" +
" public static void main(String[]argv) {\n"+
" print \"success\"\n"+
" }\n"+
"}\n",
},
"success");
}
@Test
public void testEnums() {
runConformTest(new String[] {
"p/X.groovy",
"package p;\n" +
"public enum X {\n" +
"}\n",
},
"");
}
@Test
public void testEnums2() {
try {
JDTResolver.recordInstances = true;
runConformTest(new String[] {
"EE.groovy",
"enum EE {A,B,C;}\n",
"Foo.java",
"public class Foo<E extends Foo<E>> implements Comparable<E> {" +
" public int compareTo(E b) { return 0;}\n"+
"}\n" +
"\n",
"Goo.java",
"public class Goo<X extends Goo<X>> extends Foo<X> {}\n",
"Bar.groovy",
"abstract class Bar extends Goo<Bar> {" +
" int compareTo(Bar b) { return 0;}\n"+
" EE getEnum() { return null; }\n"+
"}\n"});
// Check on the state of Comparable
JDTClassNode classnode = JDTResolver.getCachedNode("java.lang.Comparable<E>");
assertNotNull(classnode);
// Should have one method
List<MethodNode> methods = classnode.getMethods();
assertEquals(1,methods.size());
assertEquals("int compareTo(java.lang.Object)",methods.get(0).getTypeDescriptor());
classnode.lazyClassInit();
} finally {
JDTResolver.instances.clear();
JDTResolver.recordInstances=false;
}
runConformTest(new String[] {
"Foo.groovy",
"class Foo<E extends Foo<E>> implements Comparable<E> {" +
" int compareTo(Object b) { return 0;}\n"+
"}\n" +
"\n",
"Bar.groovy",
"abstract class Bar extends Foo<Bar> {" +
" int compareTo(Bar b) { return 0;}\n"+
"}\n"
});
}
@Test
public void testNonTerminalMissingImport() {
runNegativeTest(new String[] {
"p/X.groovy",
"package p;\n" +
"import a.b.c.D;\n"+
"public class X {\n" +
" public static void main(String[]argv) {\n"+
" print \"success\"\n"+
" }\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\X.groovy (at line 2)\n" +
"\timport a.b.c.D;\n" +
"\t ^\n" +
"Groovy:unable to resolve class a.b.c.D\n" +
"----------\n");
}
@Test
public void testTypeClash() {
runNegativeTest(new String[] {
"p/X.groovy",
"package p\n" +
"public class X {}",
"p/X.java",
"package p;\n" +
"public class X {}"
},
"----------\n" +
"1. ERROR in p\\X.java (at line 2)\n" +
"\tpublic class X {}\n" +
"\t ^\n" +
"The type X is already defined\n" +
"----------\n");
}
@Test
public void testCallStaticMethodFromGtoJ() {
runConformTest(new String[] {
"p/Foo.groovy",
"package p;\n" +
"public class Foo {\n" +
" public static void main(String[]argv) {\n"+
" X.run()\n"+
" }\n"+
"}\n",
"p/X.java",
"package p;\n"+
"public class X {\n"+
" public static void run() {\n"+
" System.out.println(\"success\");\n"+
" }\n"+
"}\n"
},
"success");
}
@Test
public void testCallStaticMethodFromJtoG() {
runConformTest(new String[] {
"p/Foo.java",
"package p;\n" +
"public class Foo {\n" +
" public static void main(String[]argv) {\n"+
" X.run();\n"+
" }\n"+
"}\n",
"p/X.groovy",
"package p;\n"+
"public class X {\n"+
" public static void run() {\n"+
" System.out.println(\"success\");\n"+
" }\n"+
"}\n"
},
"success");
}
@Test
public void testNotMakingInterfacesImplementGroovyObject() {
runConformTest(new String[] {
"p/X.java",
"package p;\n"+
"public class X implements I {\n"+
" public static void main(String[] argv) {\n"+
" System.out.println(\"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n" +
"public interface I {\n" +
"}\n",
},
"success");
}
@Test
public void testExtendingInterface2() {
runNegativeTest(new String[] {
"p/X.groovy",
"package p;\n" +
"public class X extends List<String> {\n" +
" public static void main(String[] argv) {\n"+
" print \"success\"\n" +
" }\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\X.groovy (at line 2)\n" +
"\tpublic class X extends List<String> {\n" +
"\t ^\n" +
"Groovy:You are not allowed to extend the interface \'java.util.List\', use implements instead.\n" +
"----------\n");
}
// WMTW: the type declaration building code creates the correct representation of A and adds the default constructor
@Test
public void testExtendingGroovyWithJava1() {
runConformTest(new String[] {
// p.B
"p/B.java",
"package p;\n"+
"public class B extends A {\n"+
" public static void main(String[] argv) {\n"+
" new B();\n"+
" System.out.println(\"success\");\n"+
" }\n"+
"}\n",
// p.A
"p/A.groovy",
"package p;\n" +
"public class A {\n" +
"}\n",
},"success");
}
// WMTW: a JDT resolver is plugged into groovy so it can see Java types
// details:
// 1. needed the lookupenvironment to flow down to the groovyparser (through initializeParser) as groovy will need it
// for resolution of JDT types
// 2. needed to subclass ResolveVisitor - trying just to override resolve(ClassNode) right now
// 3. needed to build JDTClassNode and needed it to initialize the superclass field
@Test
public void testExtendingJavaWithGroovy1() {
runConformTest(new String[] {
// p.B
"p/B.groovy",
"package p;\n" +
"public class B extends A {\n" +
" public static void main(String[] argv) {\n"+
" new B();\n"+
" System.out.println(\"success\");\n"+
" }\n"+
"}\n",
// p.A
"p/A.java",
"package p;\n"+
"public class A {\n"+
"}\n",
},"success");
}
@Test
public void testExtendingJavaWithGroovyAndThenJava() {
runConformTest(new String[] {
// p.C
"p/C.java",
"package p;\n" +
"public class C extends B {\n" +
" public static void main(String[] argv) {\n"+
" new C();\n"+
" System.out.println(\"success\");\n"+
" }\n"+
"}\n",
// p.B
"p/B.groovy",
"package p;\n" +
"public class B extends A {\n" +
"}\n",
// p.A
"p/A.java",
"package p;\n"+
"public class A {\n"+
"}\n",
},"success");
}
// Groovy is allowed to have a public class like this in a file with a different name
@Test
public void testPublicClassInWrongFile() {
runConformTest(new String[] {
"pkg/One.groovy",
"package pkg;\n" +
"public class One {" +
" public static void main(String[]argv) { print \"success\";}\n" +
"}\n"+
"public class Two {" +
" public static void main(String[]argv) { print \"success\";}\n" +
"}\n",
},"success");
}
/**
* WMTW: having a callback registered with groovy class generation that tracks which class file is created for which module node
* details:
* the groovy compilationunit provides a way to ask for the generated classes but it doesnt give a way to tell why they arose
* (which sourceunit caused them to come into existence). I am using the callback mechanism to track this information, but I worry
* that we are causing groovy to perhaps do things too many times. It also feels a little wierd that driving any single file through
* to CLASSGEN drives them all through. It isn't necessarily a problem, but it conflicts with the model of dealing with one file at
* a time...
*/
@Test
public void testBuildingTwoGroovyFiles() {
runConformTest(new String[] {
// pkg.One
"pkg/One.groovy",
"package pkg;\n" +
"class One {" +
" public static void main(String[]argv) { print \"success\";}\n" +
"}\n",
// pkg.Two
"pkg/Two.groovy",
"package pkg;\n" +
"class Two {}\n"
},"success");
}
@Test
public void testExtendingGroovyInterfaceWithJava() {
runConformTest(new String[] {
// pkg.C
"pkg/C.java",
"package pkg;\n" +
"public class C extends groovy.lang.GroovyObjectSupport implements I {" +
" public static void main(String[]argv) {\n"+
" I i = new C();\n"+
" System.out.println( \"success\");" +
" }\n" +
"}\n",
// pkg.I
"pkg/I.groovy",
"package pkg;\n" +
"interface I {}\n"
},"success");
}
@Test
public void testExtendingJavaInterfaceWithGroovy() {
runConformTest(new String[] {
// pkg.C
"pkg/C.groovy",
"package pkg;\n" +
"public class C implements I {" +
" public static void main(String[]argv) {\n"+
" I i = new C();\n"+
" System.out.println( \"success\");" +
" }\n" +
"}\n",
// pkg.I
"pkg/I.java",
"package pkg;\n" +
"interface I {}\n"
},"success");
}
// WMTM: the fix for the previous code that tracks why classes are generated
@Test
public void testExtendingJavaWithGroovyAndThenJavaAndThenGroovy() {
runConformTest(new String[] {
// p.D
"p/D.groovy",
"package p;\n" +
"class D extends C {\n" +
" public static void main(String[] argv) {\n"+
" new C();\n"+
" print \"success\"\n"+
" }\n"+
"}\n",
// p.C
"p/C.java",
"package p;\n" +
"public class C extends B {}\n",
// p.B
"p/B.groovy",
"package p;\n" +
"public class B extends A {}\n",
// p.A
"p/A.java",
"package p;\n"+
"public class A {}\n"
},"success");
}
@Test
public void testImplementingInterface1() {
runNegativeTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C extends groovy.lang.GroovyObjectSupport implements I {\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I {\n" +
" void m();\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.java (at line 2)\n" +
"\tpublic class C extends groovy.lang.GroovyObjectSupport implements I {\n" +
"\t ^\n" +
"The type C must implement the inherited abstract method I.m()\n" +
"----------\n");
}
@Test
public void testImplementingInterface2() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C extends groovy.lang.GroovyObjectSupport implements I {\n"+
" public void m() {}\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I {\n" +
" void m();\n"+
"}\n",
},"success");
}
@Test
public void testImplementingInterface3() {
runNegativeTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C extends groovy.lang.GroovyObjectSupport implements I {\n"+
" void m() {}\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I {\n" +
" void m();\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.java (at line 3)\n" +
"\tvoid m() {}\n" +
"\t ^^^\n" +
"Cannot reduce the visibility of the inherited method from I\n" +
"----------\n");
}
@Test
public void testImplementingInterface4() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C extends groovy.lang.GroovyObjectSupport implements I {\n"+
" public String m() { return \"\";}\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I {\n" +
" String m();\n"+
"}\n",
},"success");
}
// WMTW: Groovy compilation unit scope adds the extra default import for java.util so List can be seen
@Test
public void testImplementingInterface_JavaExtendingGroovyAndImplementingMethod() {
runNegativeTest(new String[] {
"p/C.java",
"package p;\n" +
"import java.util.List;\n"+
"public class C extends groovy.lang.GroovyObjectSupport implements I {\n"+
" public String m() { return \"\";}\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I {\n" +
" List m();\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.java (at line 4)\n" +
"\tpublic String m() { return \"\";}\n" +
"\t ^^^^^^\n" +
"The return type is incompatible with I.m()\n" +
"----------\n"+
// this verifies the position report for the error against the return value of the method
"----------\n" +
"1. WARNING in p\\I.groovy (at line 3)\n" +
"\tList m();\n" +
"\t^^^^\n" +
"List is a raw type. References to generic type List<E> should be parameterized\n" +
"----------\n");
}
@Test
public void testFieldPositioning01() {
runNegativeTest(new String[] {
"p/C.groovy",
"package p;\n" +
"public class C {\n"+
" List aList;\n"+
"}\n",
},
"----------\n" +
"1. WARNING in p\\C.groovy (at line 3)\n" +
"\tList aList;\n" +
"\t^^^^\n" +
"List is a raw type. References to generic type List<E> should be parameterized\n" +
"----------\n");
}
// FIXASC poor positional error for invalid field name - this test needs sorting out
@Test
public void testFieldPositioning02() {
runNegativeTest(new String[] {
"p/C.groovy",
"package p;\n" +
"public class C {\n"+
" List<String> class;\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.groovy (at line 3)\n" +
"\tList<String> class;\n" +
"\t^\n" +
"Groovy:unexpected token: List @ line 3, column 3.\n" +
"----------\n");
}
@Test
public void testImplementingInterface_JavaExtendingGroovyAndImplementingMethod_ArrayReferenceReturnType() {
runNegativeTest(new String[] {
"p/C.java",
"package p;\n" +
"import java.util.List;\n"+
"public class C extends groovy.lang.GroovyObjectSupport implements I {\n"+
" public String m() { return \"\";}\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I {\n" +
" List[] m();\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.java (at line 4)\n" +
"\tpublic String m() { return \"\";}\n" +
"\t ^^^^^^\n" +
"The return type is incompatible with I.m()\n" +
"----------\n"+
// this verifies the position report for the error against the return value of the method
"----------\n" +
"1. WARNING in p\\I.groovy (at line 3)\n" +
"\tList[] m();\n" +
"\t^^^^\n" +
"List is a raw type. References to generic type List<E> should be parameterized\n" +
"----------\n");
}
@Test
public void testImplementingInterface_JavaExtendingGroovyAndImplementingMethod_QualifiedArrayReferenceReturnType() {
runNegativeTest(new String[] {
"p/C.java",
"package p;\n" +
"import java.util.List;\n"+
"public class C extends groovy.lang.GroovyObjectSupport implements I {\n"+
" public String m() { return \"\";}\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I {\n" +
" java.util.List[] m();\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.java (at line 4)\n" +
"\tpublic String m() { return \"\";}\n" +
"\t ^^^^^^\n" +
"The return type is incompatible with I.m()\n" +
"----------\n"+
// this verifies the position report for the error against the return value of the method
"----------\n" +
"1. WARNING in p\\I.groovy (at line 3)\n" +
"\tjava.util.List[] m();\n" +
"\t^^^^^^^^^^^^^^\n" +
"List is a raw type. References to generic type List<E> should be parameterized\n" +
"----------\n");
}
@Test
public void testImplementingInterface_JavaExtendingGroovyAndImplementingMethod_ParamPosition() {
runNegativeTest(new String[] {
"p/C.java",
"package p;\n" +
"import java.util.List;\n"+
"public class C extends groovy.lang.GroovyObjectSupport implements I {\n"+
" public void m(String s) { }\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I {\n" +
" void m(List l);\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.java (at line 3)\n" +
"\tpublic class C extends groovy.lang.GroovyObjectSupport implements I {\n" +
"\t ^\n" +
"The type C must implement the inherited abstract method I.m(List)\n" +
"----------\n" +
// this verifies the position report for the error against the method parameter
"----------\n" +
"1. WARNING in p\\I.groovy (at line 3)\n" +
"\tvoid m(List l);\n" +
"\t ^^^^\n" +
"List is a raw type. References to generic type List<E> should be parameterized\n" +
"----------\n");
}
@Test
public void testImplementingInterface_JavaExtendingGroovyAndImplementingMethod_QualifiedParamPosition() {
runNegativeTest(new String[] {
"p/C.java",
"package p;\n" +
"import java.util.List;\n"+
"public class C extends groovy.lang.GroovyObjectSupport implements I {\n"+
" public void m(String s) { }\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I {\n" +
" void m(java.util.List l);\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.java (at line 3)\n" +
"\tpublic class C extends groovy.lang.GroovyObjectSupport implements I {\n" +
"\t ^\n" +
"The type C must implement the inherited abstract method I.m(List)\n" +
"----------\n" +
// this verifies the position report for the error against the method parameter+
"----------\n" +
"1. WARNING in p\\I.groovy (at line 3)\n" +
"\tvoid m(java.util.List l);\n" +
"\t ^^^^^^^^^^^^^^\n" +
"List is a raw type. References to generic type List<E> should be parameterized\n" +
"----------\n");
}
@Test
public void testImplementingInterface_MethodWithParameters_GextendsJ() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"public class C implements I<Integer> {\n"+
" public void m(String s) { }\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.java",
"package p;\n"+
"public interface I<T extends Number> {\n" +
" void m(String s);\n"+
"}\n",
},
"success");
}
// Test that the alias is recognized when referenced as superclass
// WMTW: the code Scope.getShortNameFor()
@Test
public void testImportAliasingGoober() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"import java.util.HashMap as Goober;\n"+
"public class C extends Goober {\n"+
" public static void main(String[] argv) {\n"+
" print 'q.A.run'\n"+
" }\n"+
"}\n",
},
"q.A.run");
}
@Test
public void testImportAliasing() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"import q.A as AA;\n"+
"import r.A as AB;\n"+
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" callitOne(new AA());\n"+
" callitTwo(new AB());\n"+
" }\n"+
" public static void callitOne(AA a) { a.run();}\n"+
" public static void callitTwo(AB a) { a.run();}\n"+
"}\n",
"q/A.java",
"package q;\n"+
"public class A {\n" +
" public static void run() { System.out.print(\"q.A.run \");}\n"+
"}\n",
"r/A.java",
"package r;\n"+
"public class A {\n" +
" public static void run() { System.out.print(\"r.A.run\");}\n"+
"}\n",
},
"q.A.run r.A.run");
}
@Test
public void testImportAliasingAndOldReference() {
runNegativeTest(new String[] {
"p/C.groovy",
"package p;\n" +
"import q.A as AA;\n"+
"import r.A as AB;\n"+
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" callitOne(new AA());\n"+
" }\n"+
" public static void callitOne(A a) { }\n"+ // no A imported!
"}\n",
"q/A.java",
"package q;\n"+
"public class A {\n" +
" public static void run() { System.out.print(\"q.A.run \");}\n"+
"}\n",
"r/A.java",
"package r;\n"+
"public class A {\n" +
" public static void run() { System.out.print(\"r.A.run\");}\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.groovy (at line 8)\n" +
"\tpublic static void callitOne(A a) { }\n" +
"\t ^\n" +
"Groovy:unable to resolve class A \n" +
"----------\n");
}
@Test
public void testImportInnerInner01() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"public class C {\n"+
" private static Wibble.Inner.Inner2 wibbleInner = new G();\n"+
" public static void main(String[] argv) {\n"+
" wibbleInner.run();\n"+
" }\n"+
"}\n"+
"class G extends Wibble.Inner.Inner2 {}",
"p/Wibble.java",
"package p;\n"+
"public class Wibble {\n" +
" public static class Inner {\n"+
" public static class Inner2 {\n"+
" public static void run() { System.out.print(\"p.Wibble.Inner.Inner2.run \");}\n"+
" }\n"+
" }\n"+
"}\n",
},
"p.Wibble.Inner.Inner2.run");
}
@Test
public void testImportInnerClass01_JavaCase() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"import x.y.z.Wibble.Inner;\n"+
"\n"+
"public class C {\n"+
" private static Inner wibbleInner = new Inner();\n"+
" public static void main(String[] argv) {\n"+
" wibbleInner.run();\n"+
" }\n"+
"}\n",
"x/y/z/Wibble.java",
"package x.y.z;\n"+
"public class Wibble {\n" +
" public static class Inner {\n"+
" public static void run() { System.out.print(\"q.A.run \");}\n"+
" }\n"+
"}\n",
},
"q.A.run");
}
// FIXASC need to look at all other kinds of import - statics/double nested static classes/etc
@Test
public void testImportInnerClass01_GroovyCase() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"import x.y.z.Wibble.Inner\n"+
"\n"+
"public class C {\n"+
" private static Inner wibbleInner = new Inner();\n"+
" public static void main(String[] argv) {\n"+
" wibbleInner.run();\n"+
" }\n"+
"}\n",
"x/y/z/Wibble.java",
"package x.y.z;\n"+
"public class Wibble {\n" +
" public static class Inner {\n"+
" public static void run() { System.out.print(\"q.A.run \");}\n"+
" }\n"+
"}\n",
},
"q.A.run");
}
@Test
public void testImportInnerClass() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"import x.y.z.Wibble.Inner /*as WibbleInner*/;\n"+
"public class C {\n"+
" private static Inner wibbleInner = new Inner();\n"+
" public static void main(String[] argv) {\n"+
" wibbleInner.run();\n"+
" }\n"+
//" public static void callitOne(WibbleInner a) { a.run();}\n"+
"}\n",
"x/y/z/Wibble.java",
"package x.y.z;\n"+
"public class Wibble {\n" +
" public static class Inner {\n"+
" public void run() { System.out.print(\"run\");}\n"+
" }\n"+
"}\n",
},
"run");
}
@Test
public void testImportAliasingInnerClass() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"import x.y.z.Wibble.Inner as WibbleInner;\n"+
"public class C {\n"+
" private static WibbleInner wibbleInner = new WibbleInner();\n"+
" public static void main(String[] argv) {\n"+
" wibbleInner.run();\n"+
" }\n"+
"}\n",
"x/y/z/Wibble.java",
"package x.y.z;\n"+
"public class Wibble {\n" +
" public static class Inner {\n"+
" public void run() { System.out.print(\"run \");}\n"+
" }\n"+
"}\n",
},
"run");
}
@Test
public void testImplementingInterface_MethodWithParameters_JextendsG() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C extends groovy.lang.GroovyObjectSupport implements I<Integer> {\n"+
" public void m(String s) { }\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I<T extends Number> {\n" +
" void m(String s);\n"+
"}\n",
},
"success");
}
@Test
public void testImplementingInterface_MethodWithParameters2_JextendsG() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C extends groovy.lang.GroovyObjectSupport implements I<Integer> {\n"+
" public void m(String s, Integer i) { }\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I<T extends Number> {\n" +
" void m(String s, Integer i);\n"+
"}\n",
},
"success");
}
@Test
public void testImplementingInterface_MethodWithParameters2_GextendsJ() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"public class C implements I<Integer> {\n"+
" public void m(String s, Integer i) { return null;}\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.java",
"package p;\n"+
"public interface I<T extends Number> {\n" +
" void m(String s, Integer i);\n"+
"}\n",
},
"success");
}
@Test
public void testImplementingInterface_MethodWithParameters3_GextendsJ() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"public class C implements I<Integer> {\n"+
" public void m(String s, Integer i) { return null;}\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.java",
"package p;\n"+
"public interface I<T extends Number> {\n" +
" void m(String s, T t);\n"+
"}\n",
},
"success");
}
@Test
public void testImplementingInterface_MethodWithParameters3_JextendsG() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C extends groovy.lang.GroovyObjectSupport implements I<Integer> {\n"+
" public void m(String s, Integer i) { }\n"+
" public static void main(String[] argv) {\n"+
" System.out.println( \"success\");\n"+
" }\n"+
"}\n",
"p/I.groovy",
"package p;\n"+
"public interface I<T extends Number> {\n" +
" void m(String s, T t);\n"+
"}\n",
},
"success");
}
@Test
public void testCallingMethods_JcallingG() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" new GClass().run();\n"+
" }\n"+
"}\n",
"p/GClass.groovy",
"package p;\n"+
"public class GClass {\n" +
" void run() {\n" +
" print \"success\"\n"+
" }\n"+
"}\n",
},
"success");
}
@Test
public void testCallingMethods_GcallingJ() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" new OtherClass().run();\n"+
" }\n"+
"}\n",
"p/OtherClass.java",
"package p;\n"+
"public class OtherClass {\n" +
" void run() {\n" +
" System.out.println(\"success\");\n"+
" }\n"+
"}\n",
},
"success");
}
@Test
public void testReferencingFields_JreferingToG() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" OtherClass oClass = new OtherClass();\n"+
" System.out.println(oClass.message);\n"+
" }\n"+
"}\n",
"p/OtherClass.groovy",
"package p;\n"+
"public class OtherClass {\n" +
" public String message =\"success\";\n"+
"}\n",
},
"success");
}
@Test
public void testReferencingFields_GreferingToJ() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" OtherClass oClass = new OtherClass();\n"+
" System.out.println(oClass.message);\n"+
" }\n"+
"}\n",
"p/OtherClass.java",
"package p;\n"+
"public class OtherClass {\n" +
" public String message =\"success\";\n"+
"}\n",
},
"success");
}
@Test
public void testCallingConstructors_JcallingG() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" OtherClass oClass = new OtherClass();\n"+
" System.out.println(\"success\");\n"+
" }\n"+
"}\n",
"p/OtherClass.groovy",
"package p;\n"+
"public class OtherClass {\n" +
" public OtherClass() {\n"+
" }\n"+
"}\n",
},
"success");
}
@Test
public void testCallingConstructors_GcallingJ() {
runConformTest(new String[] {
"p/C.groovy",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" OtherClass oClass = new OtherClass();\n"+
" System.out.println(\"success\");\n"+
" }\n"+
"}\n",
"p/OtherClass.java",
"package p;\n"+
"public class OtherClass {\n" +
" public OtherClass() {\n"+
" }\n"+
"}\n",
},
"success");
}
@Test
public void testGroovyObjectsAreGroovyAtCompileTime() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" groovy.lang.GroovyObject oClass = new OtherClass();\n"+
" System.out.println(\"success\");\n"+
" }\n"+
"}\n",
"p/OtherClass.groovy",
"package p;\n"+
"import java.util.*;\n"+
"public class OtherClass {\n" +
"}\n",
},
"success");
}
@Test
public void testCallGroovyObjectMethods_invokeMethod() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" groovy.lang.GroovyObject oClass = new OtherClass();\n"+
" String s = (String)oClass.invokeMethod(\"toString\",null);\n"+
" System.out.println(s);\n"+
" }\n"+
"}\n",
"p/OtherClass.groovy",
"package p;\n"+
"import java.util.*;\n"+
"public class OtherClass {\n" +
" String toString() { return \"success\";}\n"+
"}\n",
},
"success");
}
@Test
public void testGroovyObjectsAreGroovyAtRunTime() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" OtherClass oClass = new OtherClass();\n"+
" System.out.println(oClass instanceof groovy.lang.GroovyObject);\n"+
" }\n"+
"}\n",
"p/OtherClass.groovy",
"package p;\n"+
"import java.util.*;\n"+
"public class OtherClass {\n" +
"}\n",
},
"true");
}
@Test
public void testGroovyBug() {
runConformTest(new String[] {
"p/A.groovy",
"package p;\n" +
"public class A<T> { public static void main(String[]argv) { print \"a\";}}\n",
"p/B.groovy",
"package p;\n" +
"public class B extends A<String> {}",
},
"a");
}
@Test
public void testGroovyBug2() {
runConformTest(new String[] {
"p/B.groovy",
"package p;\n" +
"public class B extends A<String> {public static void main(String[]argv) { print \"a\";}}",
"p/A.groovy",
"package p;\n" +
"public class A<T> { }\n",
},
"a");
}
// was worried <clinit> would surface in list of methods used to build the type declaration, but that doesn't appear to be the case
@Test
public void testExtendingGroovyObjects_clinit() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" OtherClass oClass = new OtherClass();\n"+
" System.out.println(\"success\");\n"+
" }\n"+
"}\n",
"p/OtherClass.groovy",
"package p;\n"+
"public class OtherClass {\n" +
" { int i = 5; }\n" +
"}\n",
},
"success");
}
@Test
public void testGroovyPropertyAccessors_ErrorCases1() {
// check no duplicate created for 'String getProp'
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G();\n"+
" System.out.print(o.getProp());\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" String prop = 'foo'\n"+
" String getProp() { return prop; }\n"+
"}\n",
},
"foo");
}
@Test
public void testGroovyPropertyAccessors_ErrorCases2() {
// check no duplicate created for 'boolean isProp'
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G();\n"+
" System.out.print(o.isProp());\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" boolean prop = false\n"+
" boolean isProp() { return prop; }\n"+
"}\n",
},
"false");
}
@Test
public void testGroovyPropertyAccessors_ErrorCases3() {
// although there is a getProp already defined, it takes a parameter
// so a new one should still be generated
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G();\n"+
" System.out.print(o.getProp());\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" String prop = 'foo'\n"+
" String getProp(String s) { return prop; }\n"+
"}\n",
},
"foo");
}
@Test
public void testGroovyPropertyAccessors_ErrorCases4() {
// although there is a setProp already defined, it takes no parameters
// so a new one should still be generated
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G();\n"+
" o.setProp(\"abc\");\n"+
" System.out.print(\"abc\");\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" String prop = 'foo'\n"+
" void setProp() { }\n"+
"}\n",
},
"abc");
}
@Test
public void testGroovyPropertyAccessors_ErrorCases5() {
runNegativeTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G();\n"+
" o.setProp(new H());\n"+
" System.out.print(\"abc\");\n"+
" }\n"+
"}\n",
"p/H.java",
"package p;\n"+
"class H{}\n",
"p/J.java",
"package p;\n"+
"class J{}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" H prop\n"+
" void setProp(J b) { }\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.java (at line 5)\n" +
"\to.setProp(new H());\n" +
"\t ^^^^^^^\n" +
"The method setProp(J) in the type G is not applicable for the arguments (H)\n" +
"----------\n");
}
@Test
public void testGroovyPropertyAccessors_ErrorCases6() {
runNegativeTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G();\n"+
" o.setProp(\"abc\");\n"+
" System.out.print(\"abc\");\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" String prop = 'foo'\n"+
" void setProp(boolean b) { }\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\C.java (at line 5)\n" +
"\to.setProp(\"abc\");\n" +
"\t ^^^^^^^\n" +
"The method setProp(boolean) in the type G is not applicable for the arguments (String)\n" +
"----------\n");
}
@Test
public void testGroovyPropertyAccessors() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G();\n"+
" System.out.print(o.isB());\n"+
" System.out.print(o.getB());\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" boolean b\n"+
"}\n",
},
"falsefalse");
}
@Test
public void testGroovyPropertyAccessors_Set() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G();\n"+
" System.out.print(o.getB());\n"+
" o.setB(true);\n"+
" System.out.print(o.getB());\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" boolean b\n"+
"}\n",
},
"falsetrue");
}
@Test
public void testDefaultValueMethods() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G();\n"+
" o.m(\"abc\",3);\n"+
" o.m(\"abc\");\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" public void m(String s,Integer i=3) { print s }\n"+
"}\n",
},
"abcabc");
String expectedOutput =
"package p;\n" +
"public class G {\n" +
" public G() {\n" +
" }\n" +
" public void m(public String s, public Integer i) {\n" +
" }\n" +
" public void m(public String s) {\n" +
" }\n" +
"}\n";
checkGCUDeclaration("G.groovy",expectedOutput);
expectedOutput =
" \n" +
" public void m(String s, Integer i);\n" +
" \n";
checkDisassemblyFor("p/G.class", expectedOutput, ClassFileBytesDisassembler.COMPACT);
expectedOutput =
" \n" +
" public void m(String s);\n" +
" \n";
checkDisassemblyFor("p/G.class", expectedOutput, ClassFileBytesDisassembler.COMPACT);
}
@Test
public void testDefaultValueMethods02() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G();\n"+
" String str=\"xyz\";\n"+
" o.m(str,1,str,str,4.0f,str);\n"+
" o.m(str,1,str,str,str);\n"+
" o.m(str,1,str,str);\n"+
" o.m(str,str,str);\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" public void m(String s, Integer i=3, String j=\"abc\", String k, float f = 3.0f, String l) { print s+f }\n"+
"}\n",
},
"xyz4.0xyz3.0xyz3.0xyz3.0");
String expectedOutput =
"package p;\n" +
"public class G {\n" +
" public G() {\n" +
" }\n" +
" public void m(public String s, public Integer i, public String j, public String k, public float f, public String l) {\n" +
" }\n" +
" public void m(public String s, public Integer i, public String j, public String k, public String l) {\n" +
" }\n" +
" public void m(public String s, public Integer i, public String k, public String l) {\n" +
" }\n" +
" public void m(public String s, public String k, public String l) {\n" +
" }\n" +
"}\n";
checkGCUDeclaration("G.groovy", expectedOutput);
expectedOutput =
" \n" +
" public void m(String s, Integer i, String j, String k, float f, String l);\n" +
" \n";
checkDisassemblyFor("p/G.class", expectedOutput, ClassFileBytesDisassembler.COMPACT);
expectedOutput =
" \n" +
" public void m(String s, Integer i, String j, String k, String l);\n" +
" \n";
checkDisassemblyFor("p/G.class", expectedOutput, ClassFileBytesDisassembler.COMPACT);
expectedOutput =
" \n" +
" public void m(String s, Integer i, String k, String l);\n" +
" \n";
checkDisassemblyFor("p/G.class", expectedOutput, ClassFileBytesDisassembler.COMPACT);
expectedOutput =
" \n" +
" public void m(String s, String k, String l);\n" +
" \n";
checkDisassemblyFor("p/G.class", expectedOutput, ClassFileBytesDisassembler.COMPACT);
}
@Test
public void testDefaultValueConstructors() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G(2,\"abc\");\n"+
" o.print();\n"+
" o = new G(3);\n"+
" o.print();\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" def msg\n"+
" public G(Integer i, String m=\"abc\") {this.msg = m;}\n"+
" public void print(int i=3) { print msg }\n"+
"}\n",
},
"abcabc");
String expectedOutput=
"package p;\n" +
"public class G {\n" +
" private java.lang.Object msg;\n" +
" public G(public Integer i, public String m) {\n" +
" }\n" +
" public G(public Integer i) {\n" +
" }\n" +
" public void print(public int i) {\n" +
" }\n" +
" public void print() {\n" +
" }\n" +
"}\n";
checkGCUDeclaration("G.groovy", expectedOutput );
expectedOutput =
" \n" +
" public G(Integer i, String m);\n" +
" \n";
checkDisassemblyFor("p/G.class", expectedOutput, ClassFileBytesDisassembler.COMPACT);
expectedOutput =
" \n" +
" public G(Integer i);\n" +
" \n";
checkDisassemblyFor("p/G.class", expectedOutput, ClassFileBytesDisassembler.COMPACT);
}
@Test
public void testDefaultValueConstructors02() {
runConformTest(new String[] {
"p/C.java",
"package p;\n" +
"public class C {\n"+
" public static void main(String[] argv) {\n"+
" G o = new G(2,\"abc\");\n"+
" o.print();\n"+
" o = new G(3);\n"+
" o.print();\n"+
" }\n"+
"}\n",
"p/G.groovy",
"package p;\n"+
"public class G {\n" +
" def msg\n"+
" public G(Integer i) {}\n"+
" public G(Integer i, String m=\"abc\") {this.msg = m;}\n"+
" public void print(int i=3) { print msg }\n"+
"}\n",
});
}
@Test
public void testClashingMethodsWithDefaultParams() {
runNegativeTest(new String[] {
"p/Code.groovy",
"package p;\n"+
"\n"+
"class Code {\n"+
" public void m(String s) {}\n"+
" public void m(String s, Integer i =3) {}\n"+
"}\n",
},
"----------\n" +
"1. ERROR in p\\Code.groovy (at line 5)\n" +
"\tpublic void m(String s, Integer i =3) {}\n" +
"\t^"+(GroovyUtils.isAtLeastGroovy(20)?"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^":"")+"\n" +
"Groovy:The method with default parameters \"void m(java.lang.String, java.lang.Integer)\" defines a method \"void m(java.lang.String)\" that is already defined.\n"+
"----------\n"
);
}
@Test
public void testCallingJavaFromGroovy1() throws Exception {
runConformTest(new String[] {
"p/Code.groovy",
"package p;\n"+
"class Code {\n"+
" public static void main(String[] argv) {\n"+
" new J().run();\n"+
" print new J().name;\n"+
" }\n"+
"}\n",
"p/J.java",
"package p;\n"+
"public class J {\n"+
" public String name = \"name\";\n"+
" public void run() { System.out.print(\"success\"); }\n"+
"}\n",
},"successname");
//checkDisassembledClassFile(OUTPUT_DIR + File.separator + "p/Code.class", "Code", "");
}
@Test
public void testCallingJavaFromGroovy2() throws Exception {
runConformTest(new String[] {
"p/Code.groovy",
"package p;\n"+
"@Wibble(value=4)\n"+
"class Code {\n"+
" public static void main(String[] argv) {\n"+
" new J().run();\n"+
" }\n"+
"}\n",
"p/J.java",
"package p;\n"+
"public class J {\n"+
" public String name = \"name\";\n"+
" public void run() { System.out.print(\"success\"); }\n"+
"}\n",
"p/Wibble.java",
"package p;\n"+
"public @interface Wibble {\n"+
" int value() default 3;\n"+
"}\n",
},"success");
}
@Test
public void testExtendingRawJavaType() {
runConformTest(new String[] {
"p/Foo.groovy",
"package p;\n"+
"public class Foo extends Supertype {\n"+
" public static void main(String[] argv) {\n"+
" System.out.print(\"success\");\n"+
" }\n"+
"}\n",
"p/Supertype.java",
"package p;\n"+
"class Supertype<T> extends Supertype2 { }",
"p/Supertype2.java",
"package p;\n"+
"class Supertype2<T> { }"
},"success");
}
@Test
public void testTypeVariableBoundIsRawType() {
runConformTest(new String[] {
"p/Foo.groovy",
"package p;\n"+
"public class Foo extends Supertype {\n"+
" public static void main(String[] argv) {\n"+
" System.out.print(\"success\");\n"+
" }\n"+
"}\n",
"p/Supertype.java",
"package p;\n"+
"class Supertype<T extends Supertype2> { }",
"p/Supertype2.java",
"package p;\n"+
"class Supertype2<T> { }"
},"success");
}
@Test
public void testEnum() {
runConformTest(new String[] {
"p/Foo.groovy",
"package p;\n"+
"public class Foo /*extends Supertype<Goo>*/ {\n"+
" public static void main(String[] argv) {\n"+
" print Goo.R\n"+
" }\n"+
"}\n",
"p/Goo.java",
"package p;\n"+
"enum Goo { R,G,B; }",
},"R");
}
// Type already implements invokeMethod(String,Object) - should not be an error, just don't add the method
@Test
public void testDuplicateGroovyObjectMethods() {
runConformTest(new String[] {
"p/Foo.groovy",
"package p;\n"+
"public class Foo /*extends Supertype<Goo>*/ {\n"+
" public Object invokeMethod(String s, Object o) {\n" +
" return o;}\n"+
" public static void main(String[] argv) {\n"+
" print \"success\"\n"+
" }\n"+
"}\n",
},"success");
}
@Test
public void testDuplicateGroovyObjectMethods2() {
runConformTest(new String[] {
"p/Foo.groovy",
"package p;\n"+
"public class Foo /*extends Supertype<Goo>*/ {\n"+
" public MetaClass getMetaClass() {return null;}\n"+
" public void setMetaClass(MetaClass mc) {}\n"+
" public Object getProperty(String propertyName) {return null;}\n"+
" public void setProperty(String propertyName,Object newValue) {}\n"+
" public static void main(String[] argv) {\n"+
" print \"success\"\n"+
" }\n"+
"}\n",
},"success");
}
@Test
public void testTwoTopLevelTypesInAFile() {
runConformTest(new String[] {
"p/First.groovy",
"package p;\n"+
"public class First {\n"+
" public static void main(String[] argv) {\n"+
" print \"success\"\n"+
" }\n"+
"}\n"+
"class Second {\n"+
"}\n",
},"success");
}
@Test
public void testImports1() {
runConformTest(new String[] {
"p/First.groovy",
"package p;\n"+
"import java.util.regex.Pattern\n"+
"public class First {\n"+
" public static void main(String[] argv) {\n"+
" Pattern p = Pattern.compile(\".\")\n"+
" print \"success\"\n"+
" }\n"+
" public Pattern getPattern() { return null;}\n"+
"}\n",
},"success");
}
@Test
public void testImports2() {
runConformTest(new String[] {
"p/First.groovy",
"package p;\n"+
"import java.util.regex.Pattern\n"+
"public class First {\n"+
" public static void main(String[] argv) {\n"+
" print \"success\"\n"+
" }\n"+
" public File getFile() { return null;}\n"+ // java.io.File should be picked up magically
"}\n",
},"success");
}
@Test
public void testImportsBigDecimal1() {
runConformTest(new String[] {
"p/Main.java",
"package p;\n" +
"public class Main {\n" +
" public static void main(String[] args) {\n" +
" System.out.print(new Big().getAmount().toString());\n" + // https://github.com/groovy/groovy-eclipse/issues/268
" }\n" +
"}",
"p/Big.groovy",
"package p\n" +
"class Big {\n" +
" BigDecimal amount = 3.14\n" +
"}"
}, "3.14");
}
@Test
public void testImportsBigDecimal2() {
runConformTest(new String[] {
"p/Big.groovy",
"package p\n" +
"class Big {\n" +
" static void main(String[] args) {\n" +
" print 'success'\n" +
" }\n" +
" BigDecimal getAmount() { return 0 }\n" +
"}"
}, "success");
}
@Test
public void testImportsBigDecimal3() {
// this version has an import; that can make a difference...
runConformTest(new String[] {
"p/Big.groovy",
"package p\n" +
"import java.util.regex.Pattern\n" +
"class Big {\n" +
" static void main(String[] args) {\n" +
" print 'success'\n" +
" }\n" +
" BigDecimal getAmount() { return 0 }\n" +
"}"
}, "success");
}
@Test
public void testImportsBigDecimal4() {
runConformTest(new String[] {
"p/Big.groovy",
"package p\n" +
"class Big {\n" +
" static void main(String[] args) {\n" +
" print 'success'\n" +
" }\n" +
" private static final BigDecimal FIXED_AMOUNT = BigDecimal.TEN\n" +
"}"
}, "success");
}
@Test
public void testImportsBigInteger1() {
runConformTest(new String[] {
"p/Main.java",
"package p;\n" +
"public class Main {\n" +
" public static void main(String[] args) {\n" +
" System.out.print(new Big().getAmount().toString());\n" +
" }\n" +
"}",
"p/Big.groovy",
"package p\n" +
"class Big {\n" +
" BigInteger amount = 10\n" +
"}"
}, "10");
}
@Test
public void testImportsBigInteger2() {
runConformTest(new String[] {
"p/Big.groovy",
"package p\n" +
"class Big {\n" +
" static void main(String[] args) {\n" +
" print 'success'\n" +
" }\n" +
" BigInteger getAmount() { return 0 }\n" +
"}"
}, "success");
}
@Test
public void testImportsBigInteger3() {
runConformTest(new String[] {
"p/Big.groovy",
"package p\n" +
"class Big {\n" +
" static void main(String[] args) {\n" +
" print 'success'\n" +
" }\n" +
" private static final BigInteger FIXED_AMOUNT = BigInteger.TEN\n" +
"}"
}, "success");
}
@Test
public void testMultipleTypesInOneFile01() {
runConformTest(new String[] {
"p/Foo.groovy",
"package p;\n"+
"class Foo {\n"+
" public static void main(String[] argv) {\n"+
" print \"success\"\n"+
" }\n"+
"}\n"+
"class Goo {}\n"
},"success");
}
// Refering to the secondary type from the primary (but internally to a method)
@Test
public void testMultipleTypesInOneFile02() {
runConformTest(new String[] {
"p/Foo.groovy",
"package p;\n"+
"class Foo {\n"+
" public static void main(String[] argv) {\n"+
" new Goo();\n"+
" print \"success\"\n"+
" }\n"+
"}\n"+
"class Goo {}\n"
},"success");
}
// Refering to the secondary type from the primary - from a method param
@Test
public void testMultipleTypesInOneFile03() {
runConformTest(new String[] {
"p/Foo.groovy",
"package p;\n"+
"class Foo {\n"+
" public static void main(String[] argv) {\n"+
" new Foo().runnit(new Goo());\n"+
" }\n"+
" public void runnit(Goo g) {"+
" print \"success\"\n"+
" }\n"+
"}\n"+
"class Goo {}\n"
},"success");
}
// Refering to the secondary type from the primary - from a method
@Test
public void testJDKClasses() {
runConformTest(new String[] {
"p/Foo.groovy",
"package p;\n"+
"class Foo {\n"+
" public static void main(String[] argv) {\n"+
" new Foo().runnit(new Goo());\n"+
" }\n"+
" public void runnit(Goo g) {"+
" print \"success\"\n"+
" }\n"+
"}\n"+
"class Goo {}\n"
},"success");
}
// Test that the (package visible) source type in another package is visible to a groovy type
@Test
public void testVisibility() {
runConformTest(new String[] {
"p/First.groovy",
"package p;\n"+
"import q.Second;\n"+
"public class First {\n"+
" public static void main(String[] argv) {\n"+
" new First().getIt();\n"+
" print \"success\"\n"+
" }\n"+
" public Second getIt() { return null;}\n"+
"}\n",
"q/Second.java",
"package q;\n"+
"class Second {}\n",
},"success");
}
@Test
public void testClosuresBasic() {
runConformTest(new String[] {
"Coroutine.groovy",
"def iterate(n, closure) {\n"+
" 1.upto(n) {\n" +
" closure(it);\n" +
" }\n"+
"}\n"+
"iterate (3) {\n"+
" print it\n"+
"}\n"
},
"123");
}
@Test
public void testScriptWithError() {
runNegativeTest(new String[] {
"Foo.groovy",
"print Coolio!",
},
"----------\n" +
"1. ERROR in Foo.groovy (at line 1)\n" +
"\tprint Coolio!\n" +
"\t ^\n" +
"Groovy:expecting EOF, found \'!\' @ line 1, column 13.\n" +
"----------\n"
);
}
@Test
public void testScript() {
runConformTest(new String[] {
"Foo.groovy",
"print 'Coolio'\n",
},"Coolio");
}
@Test
public void testScriptCallJava() {
runConformTest(new String[] {
"Foo.groovy",
"print SomeJava.constant\n",
"SomeJava.java",
"class SomeJava { static String constant = \"abc\";}"
},"abc");
}
@Test
public void testExtraImports() throws Exception {
Map<String, String> options = getCompilerOptions();
options.put(CompilerOptions.OPTIONG_GroovyExtraImports, "com.foo.*");
options.put(CompilerOptions.OPTIONG_GroovyProjectName, "Test");
// From:
// http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/examples/transforms/local
runConformTest(
new String[] {
// @formatter:off
"com/bar/Runner.groovy",
"package com.bar\n"
+
// "import com.foo.*\n" + // this is what needs
// 'simulating'
"class Runner {\n"+
" public static void main(String[]argv) {\n"+
" Type.m();\n"+
" print 'done'\n"+
" }\n"+
"}\n",
"com/foo/Type.groovy",
"package com.foo\n" +
"class Type {\n"+
" public static void m() {}\n"+
"}\n",
// @formatter:on
}, "done", options);
}
@Test
public void testExtraImports_exactType() throws Exception {
Map<String, String> options = getCompilerOptions();
options.put(CompilerOptions.OPTIONG_GroovyExtraImports, "com.foo.Type");
options.put(CompilerOptions.OPTIONG_GroovyProjectName, "Test");
// From:
// http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/examples/transforms/local
runConformTest(new String[] {
// @formatter:off
"com/bar/Runner.groovy",
"package com.bar\n"
+
// "import com.foo.*\n" + // this is what needs
// 'simulating'
"class Runner {\n"
+ " public static void main(String[]argv) {\n"
+ " Type.m();\n" + " print 'done'\n" + " }\n"
+ "}\n",
"com/foo/Type.groovy",
"package com.foo\n" + "class Type {\n"
+ " public static void m() {}\n" + "}\n",
// @formatter:on
}, "done", options);
}
@Test
public void testExtraImports_withSuffixDotStar() throws Exception {
Map<String, String> options = getCompilerOptions();
options.put(CompilerOptions.OPTIONG_GroovyExtraImports,
".groovy=com.foo.*");
options.put(CompilerOptions.OPTIONG_GroovyProjectName, "Test");
// From:
// http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/examples/transforms/local
runConformTest(new String[] {
// @formatter:off
"com/bar/Runner.groovy",
"package com.bar\n"
+
// "import com.foo.*\n" + // this is what needs
// 'simulating'
"class Runner {\n"
+ " public static void main(String[]argv) {\n"
+ " Type.m();\n" + " print 'done'\n" + " }\n"
+ "}\n",
"com/foo/Type.groovy",
"package com.foo\n" + "class Type {\n"
+ " public static void m() {}\n" + "}\n",
// @formatter:on
}, "done", options);
}
@Test
public void testExtraImports_withSuffixExactType() throws Exception {
Map<String, String> options = getCompilerOptions();
options.put(CompilerOptions.OPTIONG_GroovyExtraImports, ".groovy=com.foo.Type");
options.put(CompilerOptions.OPTIONG_GroovyProjectName, "Test");
// From:
// http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/examples/transforms/local
runConformTest(new String[] {
// @formatter:off
"com/bar/Runner.groovy",
"package com.bar\n"
+
// "import com.foo.*\n" + // this is what needs
// 'simulating'
"class Runner {\n"
+ " public static void main(String[]argv) {\n"
+ " Type.m();\n" + " print 'done'\n" + " }\n"
+ "}\n",
"com/foo/Type.groovy",
"package com.foo\n" + "class Type {\n"
+ " public static void m() {}\n" + "}\n",
// @formatter:on
}, "done", options);
}
@Test
public void testExtraImports_withSuffixExactType2() throws Exception {
Map<String, String> options = getCompilerOptions();
options.put(CompilerOptions.OPTIONG_GroovyExtraImports, ".groovy=com.foo.Type;.groovy=com.foo.TypeB");
options.put(CompilerOptions.OPTIONG_GroovyProjectName, "Test");
// From:
// http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/examples/transforms/local
runConformTest(new String[] {
// @formatter:off
"com/bar/Runner.groovy",
"package com.bar\n"
+
// "import com.foo.*\n" + // this is what needs
// 'simulating'
"class Runner {\n"
+ " public static void main(String[]argv) {\n"
+ " Type.m();\n" + " TypeB.m();\n"
+ " print 'done'\n" + " }\n" + "}\n",
"com/foo/Type.groovy",
"package com.foo\n" + "class Type {\n"
+ " public static void m() {}\n" + "}\n",
"com/foo/TypeB.groovy",
"package com.foo\n" + "class TypeB {\n"
+ " public static void m() {}\n" + "}\n",
// @formatter:on
}, "done", options);
}
@Test
public void testExtraImports_noneMatchingSuffix() throws Exception {
Map<String, String> options = getCompilerOptions();
options.put(CompilerOptions.OPTIONG_GroovyExtraImports, ".gradle=com.foo.Type");
options.put(CompilerOptions.OPTIONG_GroovyProjectName, "Test");
// From:
// http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/examples/transforms/local
runConformTest(new String[] {
// @formatter:off
"com/bar/Runner.groovy",
"package com.bar\n"
+
// "import com.foo.*\n" + // this is what needs
// 'simulating'
"class Runner {\n"
+ " public static void main(String[]argv) {\n"
+ " Type.m();\n" + " print 'done'\n" + " }\n"
+ "}\n",
"com/foo/Type.groovy",
"package com.foo\n" + "class Type {\n"
+ " public static void m() {}\n" + "}\n",
// @formatter:on
}, "done", options);
}
@Test
public void testExtraImports_typeDoesNotExist() throws Exception {
Map<String, String> options = getCompilerOptions();
options.put(CompilerOptions.OPTIONG_GroovyExtraImports, ".groovy=com.foo.Type2");
options.put(CompilerOptions.OPTIONG_GroovyProjectName, "Test");
// From:
// http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/examples/transforms/local
runNegativeTest(new String[] {
// @formatter:off
"com/bar/Runner.groovy",
"package com.bar\n"
+
// "import com.foo.*\n" + // this is what needs
// 'simulating'
"class Runner {\n"
+ " public static void main(String[]argv) {\n"
+ " Type.m();\n" + " print 'done'\n" + " }\n"
+ "}\n",
"com/foo/Type.groovy",
"package com.foo\n" + "class Type {\n"
+ " public static void m() {}\n" + "}\n",
// @formatter:on
},
"----------\n"
+ "1. ERROR in com\\bar\\Runner.groovy (at line 4)\n"
+ "\tType.m();\n"
+ "\t^^^^\n"
+ "Groovy:Apparent variable \'Type\' was found in a static scope but doesn\'t refer to a local variable, static field or class. Possible causes:\n"
+ "----------\n", options);
}
@Test
public void testExtraImports_packageDoesNotExist() throws Exception {
Map<String, String> options = getCompilerOptions();
options.put(CompilerOptions.OPTIONG_GroovyExtraImports,
".groovy=com.madeup.*");
options.put(CompilerOptions.OPTIONG_GroovyProjectName, "Test");
// From:
// http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/examples/transforms/local
runNegativeTest(new String[] {
// @formatter:off
"com/bar/Runner.groovy",
"package com.bar\n"
+
// "import com.foo.*\n" + // this is what needs
// 'simulating'
"class Runner {\n"
+ " public static void main(String[]argv) {\n"
+ " Type.m();\n" + " print 'done'\n" + " }\n"
+ "}\n",
"com/foo/Type.groovy",
"package com.foo\n" + "class Type {\n"
+ " public static void m() {}\n" + "}\n",
// @formatter:on
},
"----------\n"
+ "1. ERROR in com\\bar\\Runner.groovy (at line 4)\n"
+ "\tType.m();\n"
+ "\t^^^^\n"
+ "Groovy:Apparent variable \'Type\' was found in a static scope but doesn\'t refer to a local variable, static field or class. Possible causes:\n"
+ "----------\n", options);
}
@Test
public void testExtraImports_multiple() throws Exception {
Map<String, String> options = getCompilerOptions();
options.put(CompilerOptions.OPTIONG_GroovyExtraImports,
".groovy=com.foo.Type,com.foo.Type2");
options.put(CompilerOptions.OPTIONG_GroovyProjectName, "Test");
// From:
// http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/examples/transforms/local
runConformTest(new String[] {
// @formatter:off
"com/bar/Runner.groovy",
"package com.bar\n"
+
// "import com.foo.*\n" + // this is what needs
// 'simulating'
"class Runner {\n"
+ " public static void main(String[]argv) {\n"
+ " Type.m();\n" + " Type2.m();\n"
+ " print 'done'\n" + " }\n"
+ "}\n",
"com/foo/Type.groovy",
"package com.foo\n" + "class Type {\n"
+ " public static void m() {}\n" + "}\n",
"com/foo/Type2.groovy",
"package com.foo\n" + "class Type2 {\n"
+ " public static void m() {}\n" + "}\n",
// @formatter:on
}, "done", options);
}
@Test
public void testExtraImports_multipleSuffixes() throws Exception {
Map<String, String> options = getCompilerOptions();
options.put(CompilerOptions.OPTIONG_GroovyExtraImports, "com.madeup.*;.groovy=com.foo.Type");
options.put(CompilerOptions.OPTIONG_GroovyProjectName, "Test");
// From:
// http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/examples/transforms/local
runConformTest(new String[] {
// @formatter:off
"com/bar/Runner.groovy",
"package com.bar\n"
+
// "import com.foo.*\n" + // this is what needs
// 'simulating'
"class Runner {\n"
+ " public static void main(String[]argv) {\n"
+ " Type.m();\n"
+ " print 'done'\n" + " }\n" + "}\n",
"com/foo/Type.groovy",
"package com.foo\n" + "class Type {\n"
+ " public static void m() {}\n" + "}\n",
// @formatter:on
}, "done", options);
}
@Test // Variable arguments
public void testInvokingVarargs01_JtoG() {
runConformTest(new String[] {
"p/Run.java",
"package p;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" X x = new X();\n"+
" x.callit();\n"+
" x.callit(1);\n"+
" x.callit(1,2);\n"+
" x.callit2();\n"+
" x.callit2(1);\n"+
" x.callit2(1,2);\n"+
" x.callit3();\n"+
" x.callit3(\"abc\");\n"+
" x.callit3(\"abc\",\"abc\");\n"+
" }\n"+
"}\n",
"p/X.groovy",
"package p;\n" +
"public class X {\n" +
" public void callit(int... is) { print is.length; }\n"+
" public void callit2(Integer... is) { print is.length; }\n"+
" public void callit3(String... ss) { print ss.length; }\n"+
"}\n",
},"012012012");
}
@Test
public void testInvokingVarargs01_GtoJ() {
runConformTest(new String[] {
"p/Run.groovy",
"package p;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" X x = new X();\n"+
" x.callit('abc');\n"+
" x.callit('abc',1);\n"+
" x.callit('abc',1,2);\n"+
" x.callit2(3);\n"+
" x.callit2(4,1);\n"+
" x.callit2(1,1,2);\n"+
" x.callit3('abc');\n"+
" x.callit3('abc',\"abc\");\n"+
" x.callit3('abc',\"abc\",\"abc\");\n"+
" }\n"+
"}\n",
"p/X.java",
"package p;\n" +
"public class X {\n" +
" public void callit(String a, int... is) { System.out.print(is.length); }\n"+
" public void callit2(int a, Integer... is) { System.out.print(is.length); }\n"+
" public void callit3(String s, String... ss) { System.out.print(ss.length); }\n"+
"}\n",
},"012012012");
}
@Test // In these two cases the methods also take other values
public void testInvokingVarargs02_JtoG() {
runConformTest(new String[] {
"p/Run.java",
"package p;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" X x = new X();\n"+
" x.callit(\"abc\");\n"+
" x.callit(\"abc\",1);\n"+
" x.callit(\"abc\",1,2);\n"+
" x.callit2(3);\n"+
" x.callit2(4,1);\n"+
" x.callit2(1,1,2);\n"+
" x.callit3(\"abc\");\n"+
" x.callit3(\"abc\",\"abc\");\n"+
" x.callit3(\"abc\",\"abc\",\"abc\");\n"+
" }\n"+
"}\n",
"p/X.groovy",
"package p;\n" +
"public class X {\n" +
" public void callit(String a, int... is) { print is.length; }\n"+
" public void callit2(int a, Integer... is) { print is.length; }\n"+
" public void callit3(String s, String... ss) { print ss.length; }\n"+
"}\n",
},"012012012");
}
@Test // Groovy doesn't care about '...' and will consider [] as varargs
public void testInvokingVarargs03_JtoG() {
runConformTest(new String[] {
"p/Run.java",
"package p;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" X x = new X();\n"+
" x.callit(\"abc\");\n"+
" x.callit(\"abc\",1);\n"+
" x.callit(\"abc\",1,2);\n"+
" x.callit2(3);\n"+
" x.callit2(4,1);\n"+
" x.callit2(1,1,2);\n"+
" x.callit3(\"abc\");\n"+
" x.callit3(\"abc\",\"abc\");\n"+
" x.callit3(\"abc\",\"abc\",\"abc\");\n"+
" }\n"+
"}\n",
"p/X.groovy",
"package p;\n" +
"public class X {\n" +
" public void callit(String a, int[] is) { print is.length; }\n"+
" public void callit2(int a, Integer[] is) { print is.length; }\n"+
" public void callit3(String s, String[] ss) { print ss.length; }\n"+
"}\n",
},"012012012");
}
@Test
public void testInners_1185() {
runConformTest(new String[] {
"WithInnerClass.groovy",
"class WithInnerClass {\n"+
"\n"+
" interface InnerInterface {\n"+
" void foo()\n"+
" }\n"+
"\n"+
" private final InnerInterface foo = new InnerInterface() {\n"+
" void foo() {\n" +
"\n" +
" }\n" +
" }\n"+
"}"
});
}
@Test
public void testInvokingVarargs02_GtoJ() {
runConformTest(new String[] {
"p/Run.groovy",
"package p;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" X x = new X();\n"+
" x.callit();\n"+
" x.callit(1);\n"+
" x.callit(1,2);\n"+
" x.callit2();\n"+
" x.callit2(1);\n"+
" x.callit2(1,2);\n"+
" x.callit3();\n"+
" x.callit3(\"abc\");\n"+
" x.callit3(\"abc\",\"abc\");\n"+
" }\n"+
"}\n",
"p/X.java",
"package p;\n" +
"public class X {\n" +
" public void callit(int... is) { System.out.print(is.length); }\n"+
" public void callit2(Integer... is) { System.out.print(is.length); }\n"+
" public void callit3(String... ss) { System.out.print(ss.length); }\n"+
"}\n",
},"012012012");
}
@Test
public void testInvokingVarargsCtors01_JtoG() {
runConformTest(new String[] {
"p/Run.java",
"package p;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" X x = null;\n"+
" x = new X();\n"+
" x = new X(1);\n"+
" x = new X(1,2);\n"+
" x = new X(\"abc\");\n"+
" x = new X(\"abc\",1);\n"+
" x = new X(\"abc\",1,2);\n"+
" }\n"+
"}\n",
"p/X.groovy",
"package p;\n" +
"public class X {\n" +
" public X(int... is) { print is.length; }\n"+
" public X(String s, int... is) { print is.length; }\n"+
"}\n",
},"012012");
}
@Test
public void testInvokingVarargsCtors01_GtoJ() {
runConformTest(new String[] {
"p/Run.groovy",
"package p;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" X x = null;\n"+
" x = new X();\n"+
" x = new X(1);\n"+
" x = new X(1,2);\n"+
" x = new X(\"abc\");\n"+
" x = new X(\"abc\",1);\n"+
" x = new X(\"abc\",1,2);\n"+
" }\n"+
"}\n",
"p/X.java",
"package p;\n" +
"public class X {\n" +
" public X(int... is) { System.out.print(is.length); }\n"+
" public X(String s, int... is) { System.out.print(is.length); }\n"+
"}\n",
},"012012");
}
@Test
public void testPositions() {
runNegativeTest(new String[] {
"One.groovy",
"class One {\n" +
" /*a*/ Stack plates;\n"+
" /*b*/ Stack plates2;\n"+
"}\n",
},"----------\n" +
"1. WARNING in One.groovy (at line 2)\n" +
"\t/*a*/ Stack plates;\n" +
"\t ^^^^^\n" +
"Stack is a raw type. References to generic type Stack<E> should be parameterized\n" +
"----------\n" +
"2. WARNING in One.groovy (at line 3)\n" +
"\t/*b*/ Stack plates2;\n" +
"\t ^^^^^\n" +
"Stack is a raw type. References to generic type Stack<E> should be parameterized\n" +
"----------\n");
}
@Test
public void testPositions_2() {
runNegativeTest(new String[] {
"One.groovy",
"class One {\n" +
" /*a*/ Stack plates;\n"+
" /*b*/ Stack plates2;\n"+
"}\n",
},"----------\n" +
"1. WARNING in One.groovy (at line 2)\n" +
"\t/*a*/ Stack plates;\n" +
"\t ^^^^^\n" +
"Stack is a raw type. References to generic type Stack<E> should be parameterized\n" +
"----------\n" +
"2. WARNING in One.groovy (at line 3)\n" +
"\t/*b*/ Stack plates2;\n" +
"\t ^^^^^\n" +
"Stack is a raw type. References to generic type Stack<E> should be parameterized\n" +
"----------\n");
}
@Test
public void testJDTClassNode_633() {
try {
JDTResolver.recordInstances = true;
runConformTest(new String[] {
"p/Run.groovy",
"package p;\n"+
"import static p.q.r.Colour.*;\n"+
"import p.q.r.Colour2;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" System.out.print(Red);\n"+
" System.out.print(Green);\n"+
" System.out.print(Blue);\n"+
" Colour2 c2 = new Colour2();\n"+
" int i = c2.compareTo('abc');\n"+
" }\n"+
"}\n",
"p/q/r/Colour.java",
"package p.q.r;\n" +
"enum Colour { Red,Green,Blue; }\n",
"p/q/r/Colour3.java",
"package p.q.r;\n"+
"@SuppressWarnings(\"rawtypes\")\n"+
"class Colour3 implements Comparable { public int compareTo(Object o) { return 0;}}\n",
"p/q/r/Colour2.java",
"package p.q.r;\n" +
"public class Colour2 implements Comparable<String> { \n"+
" public int compareTo(String s) { return 0; } \n"+
"}\n",
},"RedGreenBlue");
// Check on the state of Comparable
JDTClassNode classnode = JDTResolver.getCachedNode("java.lang.Comparable<E>");
assertNotNull(classnode);
// Should have one method
List<MethodNode> methods = classnode.getMethods();
assertEquals(1,methods.size());
assertEquals("int compareTo(java.lang.Object)", methods.get(0).getTypeDescriptor());
} finally {
JDTResolver.instances.clear();
JDTResolver.recordInstances=false;
}
}
@Test
public void testSecondaryTypeTagging() {
runConformTest(new String[] {
"Run.groovy",
"class Run { public static void main(String[]argv) {print '1.0';} }\n"+
"class B {}\n"+
"class C {}\n"+
"class D {}\n"
},"1.0");
GroovyCompilationUnitDeclaration gcud = getCUDeclFor("Run.groovy");
TypeDeclaration[] tds = gcud.types;
assertFalse((tds[0].bits&ASTNode.IsSecondaryType)!=0);
assertTrue((tds[1].bits&ASTNode.IsSecondaryType)!=0);
assertTrue((tds[2].bits&ASTNode.IsSecondaryType)!=0);
assertTrue((tds[3].bits&ASTNode.IsSecondaryType)!=0);
runConformTest(new String[] {
"Run2.groovy",
"class B {}\n"+
"class Run2 { public static void main(String[]argv) {print '1.0';} }\n"+
"class C {}\n"+
"class D {}\n"
},"1.0");
gcud = getCUDeclFor("Run2.groovy");
tds = gcud.types;
assertTrue((tds[0].bits&ASTNode.IsSecondaryType)!=0);
assertFalse((tds[1].bits&ASTNode.IsSecondaryType)!=0);
assertTrue((tds[2].bits&ASTNode.IsSecondaryType)!=0);
assertTrue((tds[3].bits&ASTNode.IsSecondaryType)!=0);
}
// FIXASC test varargs with default parameter values (methods/ctors)
@Test // static imports
public void testStaticImports_JtoG() {
runConformTest(new String[] {
"p/Run.java",
"package p;\n"+
"import static p.q.r.Colour.*;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" System.out.print(Red);\n"+
" System.out.print(Green);\n"+
" System.out.print(Blue);\n"+
" }\n"+
"}\n",
"p/q/r/Colour.groovy",
"package p.q.r;\n" +
"enum Colour { Red,Green,Blue; }\n",
},"RedGreenBlue");
}
@Test
public void testStaticImports_GtoJ() {
runConformTest(new String[] {
"p/Run.groovy",
"package p;\n"+
"import static p.q.r.Colour.*;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" System.out.print(Red);\n"+
" System.out.print(Green);\n"+
" System.out.print(Blue);\n"+
" }\n"+
"}\n",
"p/q/r/Colour.java",
"package p.q.r;\n" +
"enum Colour { Red,Green,Blue; }\n",
},"RedGreenBlue");
}
@Test
public void testStaticImports2_GtoJ() {
runConformTest(new String[] {
"p/Run.java",
"package p;\n"+
"import static p.q.r.Colour.*;\n"+
"public class Run {\n" +
" public static void main(String[] argv) {\n"+
" Red.printme();\n"+
" }\n"+
"}\n",
"p/q/r/Colour.groovy",
"package p.q.r;\n" +
"enum Colour { Red,Green,Blue; \n" +
" void printme() {\n"+
" println \"${name()}\";\n" +
" }\n"+
"}\n",
},"Red");
}
@Test
public void testStaticImportsAliasing_G() {
runConformTest(new String[] {
"p/Run.groovy",
"package p;\n"+
"import static java.lang.Math.PI\n"+
"import static java.lang.Math.sin as sine\n"+
"import static java.lang.Math.cos as cosine\n"+
"\n"+
" print sine(PI / 6) + cosine(PI / 3)"
},"1.0");
}
// Test 'import static a.B.FOO'
@Test
public void testImportStatic1() {
runConformTest(new String[] {
"b/Run.groovy",
"package b\n"+
"import static a.B.FOO\n"+
"class Run { public static void main(String[]argv) { print FOO;} }\n",
"a/B.groovy",
"package a\n"+
"class B { public static String FOO='abc';}\n",
},"abc");
GroovyCompilationUnitDeclaration gcud = getCUDeclFor("Run.groovy");
ImportReference[] irs = gcud.imports;
assertEquals("a.B.FOO",irs[0].toString().trim());
assertTrue(irs[0].isStatic());
}
// Test 'import static a.B.*'
@Test
public void testImportStatic2() {
runConformTest(new String[] {
"b/Run.groovy",
"package b\n"+
"import static a.B.*\n"+
"class Run { public static void main(String[]argv) { print FOO;} }\n",
"a/B.groovy",
"package a\n"+
"class B { public static String FOO='abc';}\n",
},"abc");
GroovyCompilationUnitDeclaration gcud = getCUDeclFor("Run.groovy");
ImportReference[] irs = gcud.imports;
assertEquals("a.B.*",irs[0].toString().trim());
assertTrue(irs[0].isStatic());
}
// Test 'import static a.B.FOO as Wibble'
@Test
public void testImportStatic3() {
runConformTest(new String[] {
"b/Run.groovy",
"package b\n"+
"import static a.B.FOO as Wibble\n"+
"class Run { public static void main(String[]argv) { print Wibble;} }\n",
"a/B.groovy",
"package a\n"+
"class B { public static String FOO='abc';}\n",
},"abc");
GroovyCompilationUnitDeclaration gcud = getCUDeclFor("Run.groovy");
ImportReference[] irs = gcud.imports;
assertTrue(irs[0] instanceof AliasImportReference);
assertEquals("a.B.FOO",irs[0].toString().trim());
assertTrue(irs[0].isStatic());
assertEquals("Wibble",new String(((AliasImportReference)irs[0]).getSimpleName()));
}
@Test
public void testImportStatic4() {
runConformTest(new String[] {
"a/B.groovy",
"package a\n"+
"interface B {\n"+
" String C = 'nls'\n" +
"}",
"x/Y.groovy",
"package x\n"+
"import static a.B.C\n" +
"class Y {\n" +
" @SuppressWarnings(C) def one() {}\n" +
" @SuppressWarnings(C) def two() {}\n" +
"}",
});
/* once was:
----------\n
1. ERROR in a\B.groovy (at line 1)\r\n
package a\r\n
^\n
Groovy:Internal groovy compiler error.\n
----------\n
*/
}
@Test
public void testParsingBlankImport_538() throws Exception {
assumeTrue(isAtLeastGroovy(21));
runNegativeTest(new String[] {
"A.groovy",
"import "
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\timport \n" +
"\t ^\n" +
"Groovy:Invalid import specification @ line 1, column 1.\n" +
"----------\n");
ModuleNode mn = getModuleNode("A.groovy");
assertNotNull(mn);
assertFalse(mn.encounteredUnrecoverableError());
List<ImportNode> imports = mn.getImports();
ImportNode brokenImportNode = imports.get(0);
assertEquals(0, brokenImportNode.getStart());
assertEquals(6, brokenImportNode.getEnd());
assertEquals("java.lang.Object", brokenImportNode.getType().getName());
ClassNode cn = mn.getClasses().get(0);
assertNotNull(cn);
assertTrue(cn.getName().equals("A"));
}
@Test
public void testParsingDotTerminatedImport_538() throws Exception {
runNegativeTest(new String[] {
"A.groovy",
"import foo."
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\timport foo.\n" +
"\t ^\n" +
"Groovy:Invalid import @ line 1, column 8.\n" +
"----------\n");
ModuleNode mn = getModuleNode("A.groovy");
assertNotNull(mn);
assertFalse(mn.encounteredUnrecoverableError());
List<ImportNode> imports = mn.getStarImports();
ImportNode brokenImportNode = imports.get(0);
assertEquals("foo.", brokenImportNode.getPackageName());
ClassNode cn = mn.getClasses().get(0);
assertNotNull(cn);
assertTrue(cn.getName().equals("A"));
}
@Test
public void testParsingBlankImportStatic_538() throws Exception {
runNegativeTest(new String[] {
"A.groovy",
"import static \n"
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\timport static \n" +
"\t ^\n" +
"Groovy:Invalid import static specification @ line 1, column 1.\n" +
"----------\n");
ModuleNode mn = getModuleNode("A.groovy");
assertNotNull(mn);
assertFalse(mn.encounteredUnrecoverableError());
Map<String, ImportNode> imports = mn.getStaticImports();
ImportNode brokenImportNode = imports.get("");
assertEquals("java.lang.Object", brokenImportNode.getType().getName());
ClassNode cn = mn.getClasses().get(0);
assertNotNull(cn);
assertTrue(cn.getName().equals("A"));
}
@Test
public void testParsingDotTerminatedImportStatic_538() throws Exception {
runNegativeTest(new String[] {
"A.groovy",
"import static foo.Bar."
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\timport static foo.Bar.\n" +
"\t ^^^^^^^\n" +
"Groovy:unable to resolve class foo.Bar\n" +
"----------\n" +
"2. ERROR in A.groovy (at line 1)\n" +
"\timport static foo.Bar.\n" +
"\t ^\n" +
"Groovy:Invalid import @ line 1, column 15.\n" +
"----------\n");
ModuleNode mn = getModuleNode("A.groovy");
assertNotNull(mn);
assertFalse(mn.encounteredUnrecoverableError());
Map<String, ImportNode> imports = mn.getStaticStarImports();
ImportNode brokenImportNode = imports.get("foo.Bar");
assertEquals("foo.Bar", brokenImportNode.getType().getName());
ClassNode cn = mn.getClasses().get(0);
assertNotNull(cn);
assertEquals("A", cn.getName());
}
@Test
public void testParsingDotTerminatedImportFollowedByClassDeclaration_538() throws Exception {
runNegativeTest(new String[] {
"A.groovy",
"import foo.\n"+
"\n"+
"class Wibble {}\n"
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\timport foo.\n" +
"\t ^\n" +
"Groovy:Invalid import @ line 1, column 8.\n" +
"----------\n");
ModuleNode mn = getModuleNode("A.groovy");
assertNotNull(mn);
assertFalse(mn.encounteredUnrecoverableError());
List<ImportNode> imports = mn.getStarImports();
ImportNode brokenImportNode = imports.get(0);
assertEquals("foo.", brokenImportNode.getPackageName());
ClassNode cn = mn.getClasses().get(0);
assertNotNull(cn);
assertEquals("Wibble", cn.getName());
}
@Test
public void testParsingDotTerminatedImportFollowedByModifierAndClassDeclaration_538() throws Exception {
runNegativeTest(new String[] {
"A.groovy",
"import foo.\n"+
"\n"+
"public class Wibble {}\n"
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\timport foo.\n" +
"\t ^\n" +
"Groovy:Invalid import @ line 1, column 8.\n" +
"----------\n");
ModuleNode mn = getModuleNode("A.groovy");
assertNotNull(mn);
assertFalse(mn.encounteredUnrecoverableError());
List<ImportNode> imports = mn.getStarImports();
ImportNode brokenImportNode = imports.get(0);
assertEquals("foo.", brokenImportNode.getPackageName());
ClassNode cn = mn.getClasses().get(0);
assertNotNull(cn);
assertEquals("Wibble", cn.getName());
}
@Test
public void testParsingBlankImportFollowedByClassDeclaration_538() throws Exception {
assumeTrue(isAtLeastGroovy(21));
runNegativeTest(new String[] {
"A.groovy",
"import\n"+
"\n"+
"public class Wibble {}\n"
},
"----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
"\timport\n" +
"\t ^\n" +
"Groovy:Invalid import specification @ line 1, column 1.\n" +
"----------\n");
ModuleNode mn = getModuleNode("A.groovy");
assertNotNull(mn);
assertFalse(mn.encounteredUnrecoverableError());
List<ImportNode> imports = mn.getImports();
ImportNode brokenImportNode = imports.get(0);
assertEquals("java.lang.Object", brokenImportNode.getType().getName());
ClassNode cn = mn.getClasses().get(0);
assertNotNull(cn);
assertEquals("Wibble", cn.getName());
}
@Test
public void testParsingIncompleteClassDeclaration_495() throws Exception {
runNegativeTest(new String[] {
"A.groovy",
"class Bar {}\n"+
"class FooTest extends Bar { }\n" +
"class BBB extends FooTes"
},
"----------\n" +
"1. ERROR in A.groovy (at line 3)\n" +
"\tclass BBB extends FooTes\n" +
"\t ^^^^^^\n" +
"Groovy:unable to resolve class FooTes \n" +
"----------\n" +
"2. ERROR in A.groovy (at line 3)\n" +
"\tclass BBB extends FooTes\n" +
"\t ^\n" +
"Groovy:Malformed class declaration @ line 3, column 24.\n" +
"----------\n");
// missing end curly, but that shouldn't cause us to discard what we successfully parsed
ModuleNode mn = getModuleNode("A.groovy");
assertNotNull(mn);
List<ClassNode> l = mn.getClasses();
for (int i = 0; i < l.size(); i++) {
System.out.println(l.get(i));
}
assertFalse(mn.encounteredUnrecoverableError());
ClassNode cn = mn.getClasses().get(2);
assertNotNull(cn);
assertEquals("FooTest", cn.getName());
cn = mn.getClasses().get(1);
assertNotNull(cn);
assertEquals("BBB", cn.getName());
}
@Test
public void testInnerClass1() throws Exception {
runConformTest(new String[] {
"A.groovy",
"def foo = new Runnable() {\n" +
" void run() {\n" +
" println \"hi!\";\n" +
" }\n" +
"}\n" +
"foo.run()"
}, "hi!");
}
@Test
public void testInnerClass2() throws Exception {
runConformTest(new String[] {
"A.groovy",
"def foo = new Runnable() {\n" +
" void run() {\n" +
" println \"bye!\";\n" +
" }\n" +
"}\n" +
"foo = new Runnable() {\n" +
" void run() {\n" +
" println \"hi!\";\n" +
" }\n" +
"}\n" +
"foo.run()"
}, "hi!");
}
@Test
public void testInnerClass3() throws Exception {
runConformTest(new String[] {
"A.groovy",
"def foo() {\n" +
" new Runnable() {\n" +
" void run() {\n" +
" println \"hi!\";\n" +
" }\n" +
" }\n" +
"}\n" +
"foo().run()"
}, "hi!");
}
@Test
public void testInnerClass4() throws Exception {
runConformTest(new String[] {
"A.groovy",
"class Foo {\n" +
" def foo = new Runnable() {\n" +
" void run() {\n" +
" println \"hi!\";\n" +
" }\n" +
" }\n" +
"}\n" +
"new Foo().foo.run()"
}, "hi!");
}
@Test
public void testInnerClass5() throws Exception {
runNegativeTest(new String[] {
"A.groovy",
"def foo = new Runnable() {\n" +
" void bad() {\n" +
" println \"hi!\";\n" +
" }\n" +
"}"
}, "----------\n" +
"1. ERROR in A.groovy (at line 1)\n" +
" def foo = new Runnable() {\n" +
" ^^^^^^^^\n" +
"Groovy:Can't have an abstract method in a non-abstract class. The class 'A$1' must be declared abstract or the method 'void run()' must be implemented.\n" +
"----------\n");
}
@Test
public void testAbstractMethodWithinEnum_STS3803() {
assumeTrue(isAtLeastGroovy(21));
runConformTest(new String[] {
"Bad.groovy",
"enum Bad {\n" +
" A() {\n" +
" @Override\n" +
" int foo() {\n" +
" 1\n" +
" }\n" +
" }\n" +
" abstract int foo()\n" +
"}"});
}
@Test @Ignore
public void testSts3930() {
runConformTest(new String[] {
"GroovyDemo.groovy",
"package demo\n"+
"class GroovyDemo {\n" +
" static <T> List someMethod(Class<T> factoryClass, ClassLoader classLoader = GroovyDemo.class.classLoader) {}\n" +
"}",
"JavaDemo.java",
"package demo;\n"+
"public class JavaDemo {\n" +
" public static void someMethod() {\n" +
" GroovyDemo.someMethod(JavaDemo.class);\n" +
" }\n" +
"}\n",
},
"");
}
@Test @Ignore("FIXASC testcase for this. infinite loops (B extends B<String>")
public void testInfiniteLoop() {
runConformTest(new String[] {
"p/B.groovy",
"package p;\n" +
"class B extends B<String> {\n" +
" public static void main(String[] argv) {\n"+
" new B();\n"+
" print \"success\"\n"+
" }\n"+
"}\n",
"p/A.java",
"package p;\n" +
"public class A<T> {}\n"
},
"");
}
//--------------------------------------------------------------------------
private void assertEventCount(int expectedCount, EventListener listener) {
if (listener.eventCount()!=expectedCount) {
fail("Expected "+expectedCount+" events but found "+listener.eventCount()+"\nEvents:\n"+listener.toString());
}
}
private void assertEvent(String eventText, EventListener listener) {
boolean found = false;
Iterator<String> eventIter = listener.getEvents().iterator();
while (eventIter.hasNext()) {
String s = eventIter.next();
if (s.equals(eventText)) {
found=true;
break;
}
}
if (!found) {
fail("Expected event '"+eventText+"'\nEvents:\n"+listener.toString());
}
}
/**
* Find the named file (which should have just been compiled) and for the named method determine
* the ClassNode for the return type and return the name of the classnode.
*/
public String getReturnTypeOfMethod(String filename,String methodname) {
ModuleNode mn = getModuleNode(filename);
ClassNode cn = mn.getClasses().get(0);
assertNotNull(cn);
MethodNode methodNode = cn.getMethod(methodname,new Parameter[]{});
assertNotNull(methodNode);
ClassNode returnType = methodNode.getReturnType();
return returnType.getName();
}
private String stringifyFieldDecl(FieldDeclaration fDecl) {
StringBuffer sb = new StringBuffer();
sb.append(fDecl.name);
sb.append(" sourceStart>sourceEnd:"+fDecl.sourceStart+">"+fDecl.sourceEnd);
sb.append(" declSourceStart>declSourceEnd:"+fDecl.declarationSourceStart+">"+fDecl.declarationSourceEnd);
sb.append(" modifiersSourceStart="+fDecl.modifiersSourceStart); // first char of decls modifiers
sb.append(" endPart1Position:"+fDecl.endPart1Position); // char after type decl ('int x,y' is space)
return sb.toString();
}
}