Skip to content

Commit bc05754

Browse files
committed
GROOVY-5746, GROOVY-6137, GROOVY-7473, GROOVY-10377
1 parent 14ded51 commit bc05754

File tree

16 files changed

+3382
-554
lines changed

16 files changed

+3382
-554
lines changed

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/basic/GroovyCompilerTestSuite.java

+29-19
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.eclipse.jdt.core.tests.util.CompilerTestSetup;
4040
import org.eclipse.jdt.core.tests.util.Util;
4141
import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
42+
import org.eclipse.jdt.core.util.ClassFormatException;
4243
import org.eclipse.jdt.groovy.core.util.ReflectionUtils;
4344
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
4445
import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
@@ -291,8 +292,24 @@ protected static ModuleNode getModuleNode(final String filename) {
291292
GroovyCompilationUnitDeclaration decl = getCUDeclFor(filename);
292293
if (decl != null) {
293294
return decl.getModuleNode();
294-
} else {
295-
return null;
295+
}
296+
return null;
297+
}
298+
299+
protected static byte[] getOutputFile(final String filename) {
300+
try {
301+
File file = new File(AbstractRegressionTest.OUTPUT_DIR + File.separator + filename);
302+
return org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
303+
} catch (IOException e) {
304+
throw new RuntimeException(e);
305+
}
306+
}
307+
308+
protected static String disassemble(final byte[] file, final int mode) {
309+
try {
310+
return ToolFactory.createDefaultClassFileBytesDisassembler().disassemble(file, "\n", mode);
311+
} catch (ClassFormatException e) {
312+
throw new RuntimeException(e);
296313
}
297314
}
298315

@@ -301,28 +318,21 @@ protected static void checkDisassemblyFor(final String filename, final String ex
301318
}
302319

303320
/**
304-
* Check the disassembly of a .class file for a particular piece of text
321+
* Checks the disassembly of a {@code .class} file for a particular piece of text.
305322
*/
306-
protected static void checkDisassemblyFor(final String filename, final String expectedOutput, final int detail) {
307-
try {
308-
File f = new File(AbstractRegressionTest.OUTPUT_DIR + File.separator + filename);
309-
byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(f);
310-
ClassFileBytesDisassembler disassembler = ToolFactory.createDefaultClassFileBytesDisassembler();
311-
String result = disassembler.disassemble(classFileBytes, "\n", detail);
312-
int index = result.indexOf(expectedOutput);
313-
if (index == -1 || expectedOutput.length() == 0) {
314-
System.out.println(Util.displayString(result, 3));
315-
}
316-
if (index == -1) {
317-
Assert.assertEquals("Wrong contents", expectedOutput, result);
318-
}
319-
} catch (Exception e) {
320-
Assert.fail(e.toString());
323+
protected static void checkDisassemblyFor(final String filename, final String expectedOutput, final int mode) {
324+
String disassembly = disassemble(getOutputFile(filename), mode);
325+
int index = disassembly.indexOf(expectedOutput);
326+
if (index == -1 || expectedOutput.length() == 0) {
327+
System.out.println(Util.displayString(disassembly, 3));
328+
}
329+
if (index == -1) {
330+
Assert.assertEquals("Wrong contents", expectedOutput, disassembly);
321331
}
322332
}
323333

324334
protected static void checkGCUDeclaration(final String filename, final String expectedOutput) {
325-
GroovyCompilationUnitDeclaration decl = ((DebugRequestor) GroovyParser.debugRequestor).declarations.get(filename);
335+
GroovyCompilationUnitDeclaration decl = getCUDeclFor(filename);
326336
String declarationContents = decl.print();
327337
if (expectedOutput == null || expectedOutput.length() == 0) {
328338
System.out.println(Util.displayString(declarationContents, 2));

base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/StaticCompilationTests.java

+164-34
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static org.eclipse.jdt.groovy.core.tests.GroovyBundle.isAtLeastGroovy;
1919
import static org.eclipse.jdt.groovy.core.tests.GroovyBundle.isParrotParser;
20+
import static org.junit.Assert.assertTrue;
2021
import static org.junit.Assume.assumeTrue;
2122

2223
import org.eclipse.jdt.groovy.core.tests.basic.GroovyCompilerTestSuite;
@@ -767,15 +768,15 @@ public void testCompileStatic5746() {
767768
"int getIndex() { i++ }\n" +
768769
"@CompileStatic void test() {\n" +
769770
" def list = ['x','y','z']\n" +
770-
" print(list[index] += '!')\n" +
771-
" print(list[index] += '!')\n" +
772-
" print(list)\n" +
771+
" assert (list[index] += '!') == 'x!'\n" +
772+
" assert (list[index] += '!') == 'y!'\n" +
773+
" print list\n" +
773774
"}\n" +
774775
"test()\n",
775776
};
776777
//@formatter:on
777778

778-
runConformTest(sources, "x!y![x!, y!, z]");
779+
runConformTest(sources, "[x!, y!, z]");
779780
}
780781

781782
@Test
@@ -800,6 +801,24 @@ public void testCompileStatic6095() {
800801
runConformTest(sources, "123.0");
801802
}
802803

804+
@Test
805+
public void testCompileStatic6137() {
806+
//@formatter:off
807+
String[] sources = {
808+
"Main.groovy",
809+
"@groovy.transform.CompileStatic\n" +
810+
"void test(a, b) {\n" +
811+
" print(a in b)\n" +
812+
"}\n" +
813+
"test(null,null)\n" +
814+
"test(null,new Object())\n" +
815+
"test(new Object(),null)\n",
816+
};
817+
//@formatter:on
818+
819+
runConformTest(sources, "truefalsefalse");
820+
}
821+
803822
@Test
804823
public void testCompileStatic6276() {
805824
//@formatter:off
@@ -1280,6 +1299,126 @@ public void testCompileStatic7363() {
12801299
runConformTest(sources, "42");
12811300
}
12821301

1302+
@Test
1303+
public void testCompileStatic7473() {
1304+
//@formatter:off
1305+
String[] sources = {
1306+
"Main.groovy",
1307+
"class Foo { String bar }\n" +
1308+
"@groovy.transform.CompileStatic\n" +
1309+
"void test(Foo foo) {\n" +
1310+
" if (foo.bar[0] in ['a','b','c']) {\n" +
1311+
" print 'abc'\n" +
1312+
" }\n" +
1313+
"}\n" +
1314+
"test(new Foo(bar:'baz'))\n",
1315+
};
1316+
//@formatter:on
1317+
1318+
runConformTest(sources, "abc");
1319+
1320+
String result = disassemble(getOutputFile("Main.class"), 1);
1321+
int pos = result.indexOf("createList");
1322+
assumeTrue(pos > 0);
1323+
1324+
// the operand should be processed only once
1325+
pos = result.indexOf("createList", pos + 1);
1326+
assertTrue(pos < 0);
1327+
}
1328+
1329+
@Test
1330+
public void testCompileStatic7473a() {
1331+
assumeTrue(isParrotParser());
1332+
1333+
//@formatter:off
1334+
String[] sources = {
1335+
"Main.groovy",
1336+
"class Foo { String bar }\n" +
1337+
"@groovy.transform.CompileStatic\n" +
1338+
"void test(Foo foo) {\n" +
1339+
" if (foo.bar[0] !in ['x','y','z']) {\n" +
1340+
" print 'not xyz'\n" +
1341+
" }\n" +
1342+
"}\n" +
1343+
"test(new Foo(bar:'baz'))\n",
1344+
};
1345+
//@formatter:on
1346+
1347+
runConformTest(sources, "not xyz");
1348+
1349+
String result = disassemble(getOutputFile("Main.class"), 1);
1350+
int pos = result.indexOf("createList");
1351+
assumeTrue(pos > 0);
1352+
1353+
// the operand should be processed only once
1354+
pos = result.indexOf("createList", pos + 1);
1355+
assertTrue(pos < 0);
1356+
}
1357+
1358+
@Test
1359+
public void testCompileStatic7473b() {
1360+
//@formatter:off
1361+
String[] sources = {
1362+
"Main.groovy",
1363+
"@groovy.transform.CompileStatic\n" +
1364+
"void test() {\n" +
1365+
" int[] accept = [1,2]\n" +
1366+
" def result = ['x','yy','zzz'].findAll { it.size() in accept }\n" +
1367+
" print result\n" +
1368+
"}\n" +
1369+
"test()\n",
1370+
};
1371+
//@formatter:on
1372+
1373+
runConformTest(sources, "[x, yy]");
1374+
}
1375+
1376+
@Test
1377+
public void testCompileStatic7473c() {
1378+
//@formatter:off
1379+
String[] sources = {
1380+
"Main.groovy",
1381+
"@groovy.transform.CompileStatic\n" +
1382+
"class C {\n" +
1383+
" int i, j\n" +
1384+
" int getA() { i++ }\n" +
1385+
" int getB() { j++ }\n" +
1386+
" void test() {\n" +
1387+
" assert a in b\n" +
1388+
" assert i == 1\n" +
1389+
" assert j == 1\n" +
1390+
" }\n" +
1391+
"}\n" +
1392+
"new C().test()\n",
1393+
};
1394+
//@formatter:on
1395+
1396+
runConformTest(sources);
1397+
}
1398+
1399+
@Test
1400+
public void testCompileStatic7473d() {
1401+
//@formatter:off
1402+
String[] sources = {
1403+
"Main.groovy",
1404+
"@groovy.transform.CompileStatic\n" +
1405+
"class C {\n" +
1406+
" int i, j\n" +
1407+
" def getA() { i++ }\n" +
1408+
" def getB() { j++; null }\n" +
1409+
" void test() {\n" +
1410+
" assert !(a in b)\n" +
1411+
" assert i == 1\n" +
1412+
" assert j == 1\n" +
1413+
" }\n" +
1414+
"}\n" +
1415+
"new C().test()\n",
1416+
};
1417+
//@formatter:on
1418+
1419+
runConformTest(sources);
1420+
}
1421+
12831422
@Test
12841423
public void testCompileStatic7490() {
12851424
for (String imports : new String[] {"import static Pogo.callable_property; import static Pogo.closure_property", "import static Pogo.*"}) {
@@ -5641,36 +5780,6 @@ public void testCompileStatic9737a() {
56415780
runConformTest(sources, "str");
56425781
}
56435782

5644-
@Test(expected = AssertionError.class)
5645-
public void testCompileStatic9737b() {
5646-
//@formatter:off
5647-
String[] sources = {
5648-
"Main.groovy",
5649-
"@groovy.transform.CompileStatic\n" +
5650-
"class C extends p.A {\n" +
5651-
" void test() {\n" +
5652-
" m('')\n" + // IncompatibleClassChangeError: Found class but interface was expected
5653-
" }\n" +
5654-
"}\n" +
5655-
"new C().test()\n",
5656-
5657-
"p/A.groovy",
5658-
"package p\n" +
5659-
"abstract class A implements I {\n" +
5660-
" static void m(Integer i) { print 'int' }\n" +
5661-
"}\n",
5662-
5663-
"p/I.java",
5664-
"package p;\n" +
5665-
"interface I {\n" +
5666-
" default void m(String s) { System.out.print(\"str\"); }\n" +
5667-
"}\n",
5668-
};
5669-
//@formatter:on
5670-
5671-
runConformTest(sources, "str");
5672-
}
5673-
56745783
@Test
56755784
public void testCompileStatic9762() {
56765785
assumeTrue(isParrotParser());
@@ -6622,4 +6731,25 @@ public void testCompileStatic10375() {
66226731

66236732
runConformTest(sources, "works");
66246733
}
6734+
6735+
@Test
6736+
public void testCompileStatic10377() {
6737+
assumeTrue(isParrotParser());
6738+
6739+
//@formatter:off
6740+
String[] sources = {
6741+
"Main.groovy",
6742+
"@groovy.transform.CompileStatic\n" +
6743+
"void test(a, b = a) {\n" +
6744+
" print(a === b)\n" +
6745+
" print(a !== b)\n" +
6746+
"}\n" +
6747+
"test(new Object())\n",
6748+
};
6749+
//@formatter:on
6750+
6751+
runConformTest(sources, "truefalse");
6752+
checkDisassemblyFor("Main.class", "if_acmpne"); // ===
6753+
checkDisassemblyFor("Main.class", "if_acmpeq"); // !==
6754+
}
66256755
}

base/org.codehaus.groovy25/src/org/codehaus/groovy/classgen/AsmClassGenerator.java

+9
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@
124124
import java.util.List;
125125
import java.util.Map;
126126
import java.util.Objects;
127+
import java.util.function.Consumer;
127128

128129
import static org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression;
129130
import static org.apache.groovy.ast.tools.ExpressionUtils.isThisOrSuper;
@@ -750,6 +751,10 @@ public void visitExpressionStatement(ExpressionStatement statement) {
750751
public void visitTernaryExpression(TernaryExpression expression) {
751752
onLineNumber(expression, "visitTernaryExpression");
752753
controller.getBinaryExpressionHelper().evaluateTernary(expression);
754+
// GRECLIPSE add -- GROOVY-7473
755+
Consumer<WriterController> callback = expression.getNodeMetaData("classgen.callback");
756+
if (callback != null) callback.accept(controller);
757+
// GRECLIPSE end
753758
}
754759

755760
public void visitDeclarationExpression(DeclarationExpression expression) {
@@ -761,6 +766,10 @@ public void visitBinaryExpression(BinaryExpression expression) {
761766
onLineNumber(expression, "visitBinaryExpression: \"" + expression.getOperation().getText() + "\" ");
762767
controller.getBinaryExpressionHelper().eval(expression);
763768
controller.getAssertionWriter().record(expression.getOperation());
769+
// GRECLIPSE add -- GROOVY-5746
770+
Consumer<WriterController> callback = expression.getNodeMetaData("classgen.callback");
771+
if (callback != null) callback.accept(controller);
772+
// GRECLIPSE end
764773
}
765774

766775
public void visitPostfixExpression(PostfixExpression expression) {

0 commit comments

Comments
 (0)