2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.jetbrains.plugins.groovy.compiler;
20 import com.intellij.compiler.CompilerConfiguration
21 import com.intellij.openapi.module.Module
22 import com.intellij.openapi.vfs.VirtualFile
23 import com.intellij.psi.PsiFile
24 import junit.framework.AssertionFailedError
29 public abstract class GroovyCompilerTest extends GroovyCompilerTestCase {
30 @Override protected void setUp() {
32 addGroovyLibrary(myModule);
35 public void testPlainGroovy() throws Throwable {
36 myFixture.addFileToProject("A.groovy", "println '239'");
38 assertOutput("A", "239");
41 public void testJavaDependsOnGroovy() throws Throwable {
42 myFixture.addClass("public class Foo {" +
43 "public static void main(String[] args) { " +
44 " System.out.println(new Bar().foo());" +
47 myFixture.addFileToProject("Bar.groovy", "class Bar {" +
53 assertOutput("Foo", "239");
56 public void testCorrectFailAndCorrect() throws Exception {
57 myFixture.addClass("public class Foo {" +
58 "public static void main(String[] args) { " +
59 " System.out.println(new Bar().foo());" +
62 final String barText = "class Bar {" + " def foo() { 239 }" + "}";
63 final PsiFile file = myFixture.addFileToProject("Bar.groovy", barText);
65 assertOutput("Foo", "239");
67 setFileText(file, "class Bar {}");
70 setFileText(file, barText);
72 assertOutput("Foo", "239");
75 private void makeShouldFail() {
78 fail("Make should fail");
80 catch (RuntimeException e) {
81 if (!(e.getCause() instanceof AssertionFailedError)) {
87 public void testRenameToJava() throws Throwable {
88 myFixture.addClass("public class Foo {" +
89 "public static void main(String[] args) { " +
90 " System.out.println(new Bar().foo());" +
95 myFixture.addFileToProject("Bar.groovy", "public class Bar {" + "public int foo() { " + " return 239;" + "}" + "}");
98 assertOutput("Foo", "239");
100 setFileName bar, "Bar.java"
103 assertOutput("Foo", "239");
106 public void testTransitiveJavaDependency() throws Throwable {
107 final VirtualFile ifoo = myFixture.addClass("public interface IFoo { int foo(); }").getContainingFile().getVirtualFile();
108 myFixture.addClass("public class Foo implements IFoo {" +
109 " public int foo() { return 239; }" +
111 final PsiFile bar = myFixture.addFileToProject("Bar.groovy", "class Bar {" +
113 "public static void main(String[] args) { " +
114 " System.out.println(new Foo().foo());" +
118 assertOutput("Bar", "239");
121 touch(bar.getVirtualFile());
123 //assertTrue(assertOneElement(make()).contains("WARNING: Groovyc stub generation failed"));
125 assertOutput("Bar", "239");
128 public void testTransitiveJavaDependencyThroughGroovy() throws Throwable {
129 myFixture.addClass("public class IFoo { void foo() {} }").getContainingFile().getVirtualFile();
130 myFixture.addFileToProject("Foo.groovy", "class Foo {\n" +
132 " public int foo() { return 239; }\n" +
134 final PsiFile bar = myFixture.addFileToProject("Bar.groovy", "class Bar extends Foo {" +
135 "public static void main(String[] args) { " +
136 " System.out.println(new Foo().foo());" +
140 assertOutput("Bar", "239");
142 deleteClassFile("IFoo");
143 touch(bar.getVirtualFile());
145 //assertTrue(assertOneElement(make()).contains("WARNING: Groovyc error"));
147 assertOutput("Bar", "239");
150 public void testTransitiveGroovyDependency() throws Throwable {
151 def foo = myFixture.addFileToProject('Foo.groovy', 'class Foo {} ')
152 def bar = myFixture.addFileToProject('Bar.groovy', 'class Bar extends Foo {}')
153 def goo = myFixture.addFileToProject('Goo.groovy', 'class Goo extends Bar {}')
156 touch(foo.virtualFile)
157 touch(goo.virtualFile)
161 public void testJavaDependsOnGroovyEnum() throws Throwable {
162 myFixture.addFileToProject("Foo.groovy", "enum Foo { FOO }")
163 myFixture.addClass("class Bar { Foo f; }")
167 public void testDeleteTransitiveJavaClass() throws Throwable {
168 myFixture.addClass("public interface IFoo { int foo(); }");
169 myFixture.addClass("public class Foo implements IFoo {" +
170 " public int foo() { return 239; }" +
172 final PsiFile bar = myFixture.addFileToProject("Bar.groovy", "class Bar {" +
174 "public static void main(String[] args) { " +
175 " System.out.println(new Foo().foo());" +
179 assertOutput("Bar", "239");
181 deleteClassFile("IFoo");
182 touch(bar.getVirtualFile());
184 //assertTrue(assertOneElement(make()).contains("WARNING: Groovyc stub generation failed"));
186 assertOutput("Bar", "239");
189 public void testGroovyDependsOnGroovy() throws Throwable {
190 myFixture.addClass("public class JustToMakeGroovyGenerateStubs {}");
191 myFixture.addFileToProject("Foo.groovy", "class Foo { }");
192 final PsiFile bar = myFixture.addFileToProject("Bar.groovy", "class Bar {" +
193 "def foo(Foo f) {}\n" +
194 "public static void main(String[] args) { " +
195 " System.out.println(239);" +
199 assertOutput("Bar", "239");
201 touch(bar.getVirtualFile());
204 assertOutput("Bar", "239");
207 public void testMakeInTests() throws Throwable {
209 myFixture.addFileToProject("tests/Super.groovy", "class Super {}");
212 myFixture.addFileToProject("tests/Sub.groovy", "class Sub {\n" +
213 " Super xxx() {}\n" +
214 " static void main(String[] args) {" +
218 myFixture.addFileToProject("tests/Java.java", "public class Java {}");
220 assertOutput("Sub", "hello");
223 public void testTestsDependOnProduction() throws Throwable {
225 myFixture.addFileToProject("src/com/Bar.groovy", "package com\n" +
227 myFixture.addFileToProject("src/com/ToGenerateStubs.java", "package com;\n" +
228 "public class ToGenerateStubs {}");
229 myFixture.addFileToProject("tests/com/BarTest.groovy", "package com\n" +
230 "class BarTest extends Bar {}");
234 public void testStubForGroovyExtendingJava() throws Exception {
235 myFixture.addClass("public class Foo {}");
236 myFixture.addFileToProject("Bar.groovy", "class Bar extends Foo {}");
237 myFixture.addClass("public class Goo extends Bar {}");
242 public void testDontApplyTransformsFromSameModule() throws Exception {
245 myFixture.addClass("public class JavaClassToGenerateStubs {}");
251 private void addTransform() throws IOException {
252 myFixture.addFileToProject("Transf.groovy", """
253 import org.codehaus.groovy.ast.*
254 import org.codehaus.groovy.control.*
255 import org.codehaus.groovy.transform.*
256 @GroovyASTTransformation(phase = CompilePhase.CONVERSION)
257 public class Transf implements ASTTransformation {
258 void visit(ASTNode[] nodes, SourceUnit sourceUnit) {
259 ModuleNode module = nodes[0]
260 for (clazz in module.classes) {
261 if (clazz.name.contains('Bar')) {
262 module.addStaticStarImport('Foo', ClassHelper.makeWithoutCaching(Foo.class))
268 myFixture.addFileToProject("Foo.groovy", "class Foo {\n" +
269 "static def autoImported() { 239 }\n" +
272 CompilerConfiguration.getInstance(getProject()).addResourceFilePattern("*.ASTTransformation");
274 myFixture.addFileToProject("META-INF/services/org.codehaus.groovy.transform.ASTTransformation", "Transf");
277 public void testApplyTransformsFromDependencies() throws Exception {
280 myFixture.addFileToProject("dependent/Bar.groovy", "class Bar {\n" +
281 " static Object zzz = autoImported()\n" +
282 " static void main(String[] args) {\n" +
287 myFixture.addFileToProject("dependent/AJavaClass.java", "class AJavaClass {}");
289 Module dep = addDependentModule();
291 addGroovyLibrary(dep);
294 assertOutput("Bar", "239", dep);
297 public void testIndirectDependencies() throws Exception {
298 myFixture.addFileToProject("dependent1/Bar1.groovy", "class Bar1 {}");
299 myFixture.addFileToProject("dependent2/Bar2.groovy", "class Bar2 extends Bar1 {}");
300 PsiFile main = myFixture.addFileToProject("Main.groovy", "class Main extends Bar2 {}");
302 Module dep1 = addModule('dependent1')
303 Module dep2 = addModule('dependent2')
304 addDependency dep2, dep1
305 addDependency myModule, dep2
307 addGroovyLibrary(dep1);
308 addGroovyLibrary(dep2);
312 touch(main.virtualFile)
316 public void testExtendFromGroovyAbstractClass() throws Exception {
317 myFixture.addFileToProject "Super.groovy", "abstract class Super {}"
318 myFixture.addFileToProject "AJava.java", "public class AJava {}"
321 myFixture.addFileToProject "Sub.groovy", "class Sub extends Super {}"
325 public void test1_7InnerClass() throws Exception {
326 myFixture.addFileToProject "Foo.groovy", """
330 def javaFile = myFixture.addFileToProject("AJava.java", "public class AJava extends Foo.Bar {}")
333 touch(javaFile.virtualFile)
337 public void testRecompileDependentClass() throws Exception {
338 def cloud = myFixture.addFileToProject("Cloud.groovy", """
340 def accessFooProperty(Foo c) {
345 myFixture.addFileToProject "Foo.groovy", """
347 def withGooParameter(Goo x) {}
349 def goo = myFixture.addFileToProject("Goo.groovy", "class Goo {}")
353 touch(cloud.virtualFile)
354 touch(goo.virtualFile)
358 public void testRecompileExpressionReferences() throws Exception {
359 def rusCon = myFixture.addFileToProject('RusCon.groovy', '''
361 Closure foo = { Seq.foo() }
363 myFixture.addFileToProject "Seq.groovy", """
364 class Seq implements RusCon {
369 touch(rusCon.virtualFile)
373 public void testRecompileImportedClass() throws Exception {
374 def bar = myFixture.addFileToProject("pack/Bar.groovy", """
379 myFixture.addFileToProject "pack/Foo.groovy", """
381 class Foo extends Goo {
383 def goo = myFixture.addFileToProject("pack/Goo.groovy", """
389 touch(bar.virtualFile)
390 touch(goo.virtualFile)
394 public void testRecompileDependentClassesWithOnlyOneChanged() throws Exception {
395 def bar = myFixture.addFileToProject("Bar.groovy", """
400 myFixture.addFileToProject "Foo.groovy", """
401 class Foo extends Bar {
406 touch(bar.virtualFile)
410 public void testDollarGroovyInnerClassUsagesInStubs() throws Exception {
411 def javaFile = myFixture.addClass("""
412 public class JavaClass {
413 public static class InnerJavaClass {}
416 myFixture.addFileToProject("WithInner.groovy", """
418 static class Inner {}
423 myFixture.addFileToProject("Usage.groovy", """
425 def foo(WithInner.Inner i) {}
426 def foo(JavaClass.InnerJavaClass i) {}
430 touch(javaFile.containingFile.virtualFile)
434 public void testDollarGroovyInnerClassUsagesInStubs2() throws Exception {
435 myFixture.addClass(""" public class JavaClass { } """)
436 myFixture.addFileToProject("WithInner.groovy", """
438 static class Inner {}
442 myFixture.addFileToProject("Usage.groovy", """
444 def foo(WithInner.Inner i) {}
451 public void testGroovyAnnotations() {
452 myFixture.addClass 'public @interface Anno { Class[] value(); }'
453 myFixture.addFileToProject 'Foo.groovy', '@Anno([String]) class Foo {}'
454 myFixture.addFileToProject 'Bar.java', 'class Bar extends Foo {}'
459 public void testGenericStubs() {
460 myFixture.addFileToProject 'Foo.groovy', 'class Foo { List<String> list }'
461 myFixture.addFileToProject 'Bar.java', 'class Bar {{ for (String s : new Foo().getList()) {} }}'
465 public void testDuplicateClassDuringCompilation() throws Exception {
466 def base = myFixture.addFileToProject('p/Base.groovy', 'package p; class Base { }').virtualFile
467 myFixture.addFileToProject('p/Indirect.groovy', '''package p
469 private static class Inner { Base b }
471 private Indirect.Inner foo(Indirect.Inner g1, Inner g2, Base b) {}
473 def foo = myFixture.addFileToProject('Foo.groovy', 'class Foo { p.Indirect foo() {} }').virtualFile
481 public void testDontRecompileUnneeded() {
482 myFixture.addFileToProject('Base.groovy', 'class Base { }')
483 def foo = myFixture.addFileToProject('Foo.groovy', 'class Foo extends Base { }').virtualFile
484 myFixture.addFileToProject('Bar.groovy', 'class Bar extends Foo { }')
485 def main = myFixture.addFileToProject('Main.groovy', 'class Main extends Bar { }').virtualFile
487 long oldBaseStamp = findClassFile("Base").modificationStamp
488 long oldMainStamp = findClassFile("Main").modificationStamp
493 assert oldMainStamp != findClassFile("Main").modificationStamp
494 assert oldBaseStamp == findClassFile("Base").modificationStamp
497 public void testPartialCrossRecompile() {
498 def used = myFixture.addFileToProject('Used.groovy', 'class Used { }')
499 def java = myFixture.addFileToProject('Java.java', 'class Java { void foo(Used used) {} }')
500 def main = myFixture.addFileToProject('Main.groovy', 'class Main extends Java { }').virtualFile
502 assertEmpty compileModule(myModule)
504 assertEmpty compileFiles(used.virtualFile, main)
506 assertEmpty compileModule(myModule)
507 assertEmpty compileModule(myModule)
509 setFileText(used, 'class Used2 {}')
511 assert findClassFile('Used') == null
513 setFileText(used, 'class Used3 {}')
514 setFileText(java, 'class Java { void foo(Used3 used) {} }')
517 assert findClassFile('Used2') == null
520 public static class IdeaModeTest extends GroovyCompilerTest {
521 @Override protected boolean useJps() { false }
524 public static class JpsModeTest extends GroovyCompilerTest {
525 @Override protected boolean useJps() { true }