From cc1c06d292a23966652ed2ea57fe783e802742ef Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 25 Mar 2024 12:05:05 +0100 Subject: [PATCH] [Groovy] convert GrAssignAutoTest to Java (IDEA-327339) GitOrigin-RevId: c048db2709575abacee716142733f01ae766960d --- .../lang/highlighting/GrAssignAutoTest.java | 405 ++++++++---------- 1 file changed, 187 insertions(+), 218 deletions(-) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignAutoTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignAutoTest.java index f1f93cf6db3d..67bbb05badac 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignAutoTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignAutoTest.java @@ -1,20 +1,27 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package org.jetbrains.plugins.groovy.lang.highlighting +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.plugins.groovy.lang.highlighting; -import com.intellij.codeInspection.InspectionProfileEntry -import com.intellij.lang.annotation.HighlightSeverity -import com.intellij.openapi.projectRoots.Sdk -import com.intellij.testFramework.IdeaTestUtil -import com.intellij.testFramework.LightProjectDescriptor -import groovy.transform.CompileStatic -import org.codehaus.groovy.control.MultipleCompilationErrorsException -import org.jetbrains.annotations.NotNull -import org.jetbrains.plugins.groovy.GroovyProjectDescriptors -import org.jetbrains.plugins.groovy.LibraryLightProjectDescriptor -import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection -import org.jetbrains.plugins.groovy.util.Slow +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.testFramework.IdeaTestUtil; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.util.containers.ContainerUtil; +import groovy.lang.GroovyShell; +import org.codehaus.groovy.control.MultipleCompilationErrorsException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.GroovyProjectDescriptors; +import org.jetbrains.plugins.groovy.LibraryLightProjectDescriptor; +import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection; +import org.jetbrains.plugins.groovy.util.Slow; -import static org.assertj.core.api.Assertions.assertThat +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; /** * Character and char are skipped intentionally. @@ -22,51 +29,45 @@ import static org.assertj.core.api.Assertions.assertThat * Current spec https://github.com/apache/groovy/blob/master/src/spec/doc/core-differences-java.adoc#conversions * Bug: https://issues.apache.org/jira/browse/GROOVY-7557 */ -@CompileStatic @Slow -class GrAssignAutoTest extends GrHighlightingTestBase { +public class GrAssignAutoTest extends GrHighlightingTestBase { - private static final String CS = '''\ + private static final String CS = """ import groovy.transform.CompileStatic - ''' + """; - private static final List types = [ - 'boolean', 'int', 'double', 'String', 'BigDecimal', 'BigInteger', 'List', 'Object', 'Thread', - 'List', 'List', 'List', 'List', 'List', 'List', 'boolean[]', - 'int[]', 'double[]', 'String[]', 'Integer[]', 'List[]', 'Object[]', 'Thread[]', 'short', 'byte', 'Set', 'Set', - 'Set', 'Set', 'Set' - ] + private static final List types = List.of( + "boolean", "int", "double", "String", "BigDecimal", "BigInteger", "List", "Object", "Thread", + "List", "List", "List", "List", "List", "List", "boolean[]", + "int[]", "double[]", "String[]", "Integer[]", "List[]", "Object[]", "Thread[]", "short", "byte", "Set", "Set", + "Set", "Set", "Set"); - private static final List booleanValues = ['true', 'false', '(Boolean)true', 'false as Boolean'] - private static final List byteValues = ['(byte) 0', '-1 as Byte', '(byte)(+2)', '126', '-127'] - private static final List shortValues = ['(short) 0', '-1 as Short', '(Short)(+2)', '-32768', '32767'] - private static final List intValues = ['0', '-1', '+1', '(Integer)(+2)', '1i', '-1I', '+1 as int', '+32768', '2E3', '-2E4', '0b101101101101', '0246', '0xffff', '-0x77', '1234_5678'] - private static final List longValues = ['0l', '-1L', '+2L', '(Long)(+2)', '+1 as long', '1234_5678_9012_3456L', '0b101101101101L', '0246L', '0xffffL', '-0x77L', '0x7fff_ffff_ffff_ffffL', 'new Long("123")'] - private static final List bigIntegerValues = ['BigInteger.valueOf(1)', '-1 as BigInteger', '+2G', '-0G', '034G', '1234_5678_9012_3456G', '0b101101101101G', '0246G', '0xffffG', '-0x77G'] - private static final List floatValues = ['1.1f', '-1.1f', '+0.002f', '-0F', '034F', '5_132.12F', '0b101101101101f', '0246F', '0xffffF', '1 as Float', '(float) 1.1'] - private static final List doubleValues = ['1.1d', '-1.1d', '+0.002d', '-0D', '034D', '12_345_132.12D', '0b101101101101d', '0246d', '0xffffD', '1 as Double', '(double) 1.1'] - private static final List bigDecimalValues = ['1.1', '-1.2', '+0.002', '-0.0', '034.0G', '12_345_132.12g', '1 as BigDecimal', '(BigDecimal) 1.1'] - private static final List objectValues = ['new Object()', 'new Thread()', '"str"', 'null'] - private static final List listValues = ['[]', '[1]', '[0L]', '[1.1]', '[1.2f]', '["str"]', 'new ArrayList<>()', '[new Object()]', '[new Thread()]'] - private static final List voidValues = ['print("")', '(Void)null'] - private static final List values = booleanValues + - byteValues + - shortValues + - intValues + - longValues + - bigIntegerValues + - floatValues + - doubleValues + - bigDecimalValues + - objectValues + - listValues + - voidValues + private static final List booleanValues = List.of("true", "false", "(Boolean)true", "false as Boolean"); + private static final List byteValues = List.of("(byte) 0", "-1 as Byte", "(byte)(+2)", "126", "-127"); + private static final List shortValues = List.of("(short) 0", "-1 as Short", "(Short)(+2)", "-32768", "32767"); + private static final List intValues = List.of("0", "-1", "+1", "(Integer)(+2)", "1i", "-1I", "+1 as int", "+32768", "2E3", "-2E4", "0b101101101101", "0246", "0xffff", "-0x77", "1234_5678"); + private static final List longValues = List.of("0l", "-1L", "+2L", "(Long)(+2)", "+1 as long", "1234_5678_9012_3456L", "0b101101101101L", "0246L", "0xffffL", "-0x77L", "0x7fff_ffff_ffff_ffffL", "new Long(\"123\")"); + private static final List bigIntegerValues = List.of("BigInteger.valueOf(1)", "-1 as BigInteger", "+2G", "-0G", "034G", "1234_5678_9012_3456G", "0b101101101101G", "0246G", "0xffffG", "-0x77G"); + private static final List floatValues = List.of("1.1f", "-1.1f", "+0.002f", "-0F", "034F", "5_132.12F", "0b101101101101f", "0246F", "0xffffF", "1 as Float", "(float) 1.1"); + private static final List doubleValues = List.of("1.1d", "-1.1d", "+0.002d", "-0D", "034D", "12_345_132.12D", "0b101101101101d", "0246d", "0xffffD", "1 as Double", "(double) 1.1"); + private static final List bigDecimalValues = List.of("1.1", "-1.2", "+0.002", "-0.0", "034.0G", "12_345_132.12g", "1 as BigDecimal", "(BigDecimal) 1.1"); + private static final List objectValues = List.of("new Object()", "new Thread()", "\"str\"", "null"); + private static final List listValues = List.of("[]", "[1]", "[0L]", "[1.1]", "[1.2f]", "[\"str\"]", "new ArrayList<>()", "[new Object()]", "[new Thread()]"); + private static final List voidValues = List.of("print(\"\")", "(Void)null"); + private static final List values = ContainerUtil.concat(booleanValues, byteValues, shortValues, intValues, + longValues, bigIntegerValues, floatValues, doubleValues, bigDecimalValues, objectValues, listValues, voidValues); - private static final List> typesXTypes = vectorProduct(types, types) - private static final List> valuesXTypes = vectorProduct(values, types) + private static final List> typesXTypes = vectorProduct(types, types); + private static final List> valuesXTypes = vectorProduct(values, types); private static List> vectorProduct(List vector1, List vector2) { - return vector1.collectMany { arg1 -> vector2.collect { arg2 -> [arg1, arg2] } } + List> result = new ArrayList<>(); + for (String a : vector1) { + for (String b : vector2) { + result.add(List.of(a, b)); + } + } + return result; } @Override @@ -74,214 +75,182 @@ class GrAssignAutoTest extends GrHighlightingTestBase { protected LightProjectDescriptor getProjectDescriptor() { return new LibraryLightProjectDescriptor(GroovyProjectDescriptors.LIB_GROOVY_2_5) { @Override - Sdk getSdk() { - return IdeaTestUtil.getMockJdk18() + public Sdk getSdk() { + return IdeaTestUtil.getMockJdk18(); } - } + }; } @Override - InspectionProfileEntry[] getCustomInspections() { [new GroovyAssignabilityCheckInspection()] as InspectionProfileEntry[] } + public InspectionProfileEntry[] getCustomInspections() { return new InspectionProfileEntry[]{new GroovyAssignabilityCheckInspection()}; } - void testParameterToLocal() { - doTest ''' - @CompileStatic - void method%3$s(%1$s param) { - %2$s local = param - } - ''', + public void testParameterToLocal() { + doTest(""" + @CompileStatic + void method%3$s(%1$s param) { + %2$s local = param + } + """, typesXTypes, - ['List -> boolean[]', 'List -> double[]', 'List -> String[]', 'List -> Object[]', 'List -> boolean[]', 'List -> String[]','List -> Object[]', - 'List -> boolean[]', 'List -> int[]', 'List -> double[]', 'List -> String[]', 'List -> Integer[]', 'List -> Object[]', - 'List -> boolean[]', 'List -> String[]', 'List -> Object[]', - 'List -> boolean[]', 'List -> String[]', 'List -> Object[]', 'List -> boolean[]', - 'List -> String[]','List -> Object[]', 'List -> Thread[]', - 'Set -> boolean[]', 'Set -> String[]', 'Set -> Object[]', - 'Set -> boolean[]', 'Set -> int[]', 'Set -> double[]', 'Set -> String[]', 'Set -> Integer[]', 'Set -> Object[]', - 'Set -> boolean[]', 'Set -> String[]', 'Set -> Object[]', - 'Set -> boolean[]', 'Set -> String[]', 'Set -> Object[]', 'Set -> Thread[]'], - ["boolean -> int", "boolean -> double", "boolean -> short", "boolean -> byte", "boolean[] -> String[]", "boolean[] -> Object[]", - "boolean[] -> int[]", "boolean[] -> double[]", - "int[] -> boolean[]", "int[] -> String[]", "int[] -> Integer[]", "int[] -> Object[]", - "double[] -> boolean[]", "double[] -> Integer[]", "double[] -> Object[]", "double[] -> String[]", - "Integer[] -> String[]", "Integer[] -> boolean[]", "Integer[] -> int[]", "Integer[] -> double[]", - "String[] -> boolean[]", - "List[] -> String[]", "List[] -> boolean[]", - "Object[] -> String[]", "Object[] -> boolean[]", - "Thread[] -> String[]", "Thread[] -> boolean[]"] + List.of( + "List -> boolean[]", "List -> double[]", "List -> String[]", "List -> Object[]", "List -> boolean[]", "List -> String[]", "List -> Object[]", + "List -> boolean[]", "List -> int[]", "List -> double[]", "List -> String[]", "List -> Integer[]", "List -> Object[]", + "List -> boolean[]", "List -> String[]", "List -> Object[]", + "List -> boolean[]", "List -> String[]", "List -> Object[]", + "List -> boolean[]", "List -> String[]", "List -> Object[]", "List -> Thread[]", + "Set -> boolean[]", "Set -> String[]", "Set -> Object[]", + "Set -> boolean[]", "Set -> int[]", "Set -> double[]", "Set -> String[]", "Set -> Integer[]", "Set -> Object[]", + "Set -> boolean[]", "Set -> String[]", "Set -> Object[]", + "Set -> boolean[]", "Set -> String[]", "Set -> Object[]", "Set -> Thread[]"), + List.of( + "boolean -> int", "boolean -> double", "boolean -> short", "boolean -> byte", "boolean[] -> String[]", "boolean[] -> Object[]", "boolean[] -> int[]", "boolean[] -> double[]", + "int[] -> boolean[]", "int[] -> String[]", "int[] -> Integer[]", "int[] -> Object[]", + "double[] -> boolean[]", "double[] -> Integer[]", "double[] -> Object[]", "double[] -> String[]", + "Integer[] -> String[]", "Integer[] -> boolean[]", "Integer[] -> int[]", "Integer[] -> double[]", + "String[] -> boolean[]", + "List[] -> String[]", "List[] -> boolean[]", + "Object[] -> String[]", "Object[] -> boolean[]", + "Thread[] -> String[]", "Thread[] -> boolean[]")); } - - void testParameterToReturn() { - doTest ''' - @CompileStatic - %2$s method%3$s(%1$s param) { - return param - } - ''', + public void testParameterToReturn() { + doTest(""" + @CompileStatic + %2$s method%3$s(%1$s param) { + return param + } + """, typesXTypes, - [], - ["boolean -> int", - "boolean -> double", - "boolean -> short", - "boolean -> byte", - "boolean[] -> int[]", - "boolean[] -> double[]", - "boolean[] -> String[]", - "boolean[] -> Object[]", - "int[] -> boolean[]", - "int[] -> String[]", - "int[] -> Integer[]", - "int[] -> Object[]", - "double[] -> boolean[]", - "double[] -> String[]", - "double[] -> Integer[]", - "double[] -> Object[]", - "String[] -> boolean[]", - "Integer[] -> boolean[]", - "Integer[] -> int[]", - "Integer[] -> double[]", - "Integer[] -> String[]", - "List[] -> boolean[]", - "List[] -> String[]", - "Object[] -> boolean[]", - "Object[] -> String[]", - "Thread[] -> boolean[]", - "Thread[] -> String[]"] + List.of(), + List.of( + "boolean -> int", "boolean -> double", "boolean -> short", "boolean -> byte", + "boolean[] -> int[]", "boolean[] -> double[]", "boolean[] -> String[]", "boolean[] -> Object[]", + "int[] -> boolean[]", "int[] -> String[]", "int[] -> Integer[]", "int[] -> Object[]", + "double[] -> boolean[]", "double[] -> String[]", "double[] -> Integer[]", "double[] -> Object[]", + "String[] -> boolean[]", + "Integer[] -> boolean[]", "Integer[] -> int[]", "Integer[] -> double[]", "Integer[] -> String[]", + "List[] -> boolean[]", "List[] -> String[]", + "Object[] -> boolean[]", "Object[] -> String[]", + "Thread[] -> boolean[]", "Thread[] -> String[]")); } - void testParameterMethodCall() { - doTest ''' - def bar%3$s(%2$s param) { - } - - @CompileStatic - def method%3$s(%1$s param) { - bar%3$s(param) - } - ''', + public void testParameterMethodCall() { + doTest(""" + def bar%3$s(%2$s param) { + } + + @CompileStatic + def method%3$s(%1$s param) { + bar%3$s(param) + } + """, typesXTypes, - ['int -> double[]', 'short -> int[]', 'short -> double[]', 'byte -> int[]', 'byte -> double[]', 'short -> Integer[]', 'byte -> Integer[]'], - [] + List.of("int -> double[]", "short -> int[]", "short -> double[]", "byte -> int[]", "byte -> double[]", "short -> Integer[]", "byte -> Integer[]"), + List.of()); } - void testReturnAssignValue() { - doTest ''' - @CompileStatic - %2$s method%3$s() { - return %1$s - } - ''', + public void testReturnAssignValue() { + doTest(""" + @CompileStatic + %2$s method%3$s() { + return %1$s + } + """, valuesXTypes, - [], - ['true -> int', 'true -> double', 'true -> short', 'true -> byte', 'false -> int', 'false -> double', 'false -> short', - 'false -> byte', '(Void)null -> int', '(Void)null -> double', '(Void)null -> BigDecimal', '(Void)null -> BigInteger', - '(Void)null -> List', '(Void)null -> Thread', '(Void)null -> List', '(Void)null -> List', - '(Void)null -> List', '(Void)null -> List', '(Void)null -> List', '(Void)null -> List', - '(Void)null -> boolean[]', '(Void)null -> int[]', '(Void)null -> double[]', '(Void)null -> String[]', - '(Void)null -> Integer[]', '(Void)null -> List[]', '(Void)null -> Object[]', '(Void)null -> Thread[]', - '(Void)null -> short', '(Void)null -> byte', '(Void)null -> Set', '(Void)null -> Set', - '(Void)null -> Set', '(Void)null -> Set', '(Void)null -> Set'] + List.of(), + List.of("true -> int", "true -> double", "true -> short", "true -> byte", "false -> int", "false -> double", "false -> short", + "false -> byte", "(Void)null -> int", "(Void)null -> double", "(Void)null -> BigDecimal", "(Void)null -> BigInteger", + "(Void)null -> List", "(Void)null -> Thread", "(Void)null -> List", "(Void)null -> List", + "(Void)null -> List", "(Void)null -> List", "(Void)null -> List", "(Void)null -> List", + "(Void)null -> boolean[]", "(Void)null -> int[]", "(Void)null -> double[]", "(Void)null -> String[]", + "(Void)null -> Integer[]", "(Void)null -> List[]", "(Void)null -> Object[]", "(Void)null -> Thread[]", + "(Void)null -> short", "(Void)null -> byte", "(Void)null -> Set", "(Void)null -> Set", + "(Void)null -> Set", "(Void)null -> Set", "(Void)null -> Set")); } - void testLocalAssignValue() { - doTest ''' - @CompileStatic - void method%3$s() { - %2$s param = %1$s - } - ''', + public void testLocalAssignValue() { + doTest(""" + @CompileStatic + void method%3$s() { + %2$s param = %1$s + } + """, valuesXTypes, - ['[0L] -> BigInteger', '(Void)null -> Object', '[1] -> int', '[1] -> double', '[0L] -> double', '[1.2f] -> double', '["str"] -> int', '["str"] -> double', '["str"] -> short', '["str"] -> byte', 'new ArrayList<>() -> boolean[]', 'new ArrayList<>() -> String[]', 'new ArrayList<>() -> Object[]'], - [ + List.of("[0L] -> BigInteger", "(Void)null -> Object", "[1] -> int", "[1] -> double", "[0L] -> double", "[1.2f] -> double", + "[\"str\"] -> int", "[\"str\"] -> double", "[\"str\"] -> short", "[\"str\"] -> byte", "new ArrayList<>() -> boolean[]", + "new ArrayList<>() -> String[]", "new ArrayList<>() -> Object[]"), + List.of( "[1] -> List", "[1] -> Set", "[1] -> Set", "[1] -> Set", - "[0L] -> List", - "[0L] -> Set", - "[0L] -> Set", - "[1.1] -> List", - "[1.1] -> Set", - "[1.1] -> Set", - "[1.2f] -> List", - "[1.2f] -> Set", - "[1.2f] -> Set", - "[\"str\"] -> List", - "[\"str\"] -> Set", - "[\"str\"] -> Set", - "[\"str\"] -> Set", - "[new Object()] -> Set", - "[new Object()] -> Set", - "[new Thread()] -> List", - "[new Thread()] -> Set", - "[new Thread()] -> Set", - "[new Thread()] -> Set" - ] + "[0L] -> List", "[0L] -> Set", "[0L] -> Set", + "[1.1] -> List", "[1.1] -> Set", "[1.1] -> Set", + "[1.2f] -> List", "[1.2f] -> Set", "[1.2f] -> Set", + "[\"str\"] -> List", "[\"str\"] -> Set", "[\"str\"] -> Set", "[\"str\"] -> Set", + "[new Object()] -> Set", "[new Object()] -> Set", + "[new Thread()] -> List", "[new Thread()] -> Set", "[new Thread()] -> Set", "[new Thread()] -> Set")); } private void doTest(String body, List> arguments, List wrongFalseByIdea, List wrongTrueByIdea) { - List falseDiff = [] - List trueDiff = [] + List falseDiff = new ArrayList<>(); + List trueDiff = new ArrayList<>(); - Set falseIssues = wrongFalseByIdea as Set - Set trueIssues = wrongTrueByIdea as Set + Set falseIssues = new HashSet<>(wrongFalseByIdea); + Set trueIssues = new HashSet<>(wrongTrueByIdea); - Set shellErrors = shellTest(body, arguments) - Set ideaErrors = ideaTest(body, arguments) - - arguments.eachWithIndex { List args, int index -> - def ideaTest = ideaErrors.contains(index) - def shellTest = shellErrors.contains(index) + Set shellErrors = shellTest(body, arguments); + Set ideaErrors = ideaTest(body, arguments); + for (int i = 0; i < arguments.size(); i++) { + List argument = arguments.get(i); + boolean ideaTest = ideaErrors.contains(i); + boolean shellTest = shellErrors.contains(i); if (ideaTest != shellTest) { - def activeIssues = ideaTest ? trueIssues : falseIssues - def activeDiff = ideaTest ? trueDiff : falseDiff - def pair = "${args[0]} -> ${args[1]}" - if (!activeIssues.remove(pair.toString())) { - activeDiff.add(pair.toString()) + Set activeIssues = ideaTest ? trueIssues : falseIssues; + List activeDiff = ideaTest ? trueDiff : falseDiff; + String pair = argument.get(0) + " -> " + argument.get(1); + if (!activeIssues.remove(pair)) { + activeDiff.add(pair); } } } - - assert falseDiff.isEmpty(), "Idea no error, groovy error : " + falseDiff.collect { "'$it'" } - assertThat(trueDiff).isEmpty() - assert falseIssues.isEmpty(), falseIssues.collect { "'$it'" } - assert trueIssues.isEmpty(), trueIssues.collect { "'$it'" } + assertEmpty(falseDiff.toString(), falseDiff); + assertEmpty(trueDiff.toString(), trueDiff); + assertEmpty(falseIssues.toString(), falseIssues); + assertEmpty(trueIssues.toString(), trueIssues); } private Set ideaTest(String body, List> arguments) { - def text = CS - - arguments.eachWithIndex { List args, int index -> - text += String.format(body, args[0], args[1], index) + StringBuilder text = new StringBuilder(CS); + for (int i = 0; i < arguments.size(); i++) { + List argument = arguments.get(i); + text.append(String.format(body, argument.get(0), argument.get(1), i)); } - def offsetLen = CS.readLines().size() - def lineCount = body.readLines().size() - 1 + final int offsetLen = StringUtil.countNewLines(CS); + final int lineCount = StringUtil.countNewLines(body); - def res = new HashSet() - myFixture.with { - configureByText('_.groovy', text) - enableInspections(customInspections) - def highlighting = doHighlighting(HighlightSeverity.ERROR) - highlighting.each { - def lineNumber = myFixture.editor.document.getLineNumber(it.startOffset) - res.add((lineNumber - offsetLen).intdiv(lineCount)) - } - return res + final HashSet res = new HashSet<>(); + myFixture.configureByText("_.groovy", text.toString()); + myFixture.enableInspections(getCustomInspections()); + List highlighting = myFixture.doHighlighting(HighlightSeverity.ERROR); + Document document = myFixture.getEditor().getDocument(); + for (HighlightInfo info : highlighting) { + res.add((document.getLineNumber(info.getStartOffset()) - offsetLen) / lineCount); } + return res; } private static Set shellTest(String body, List> arguments) { - def res = new HashSet() - def shell = new GroovyShell() - arguments.eachWithIndex { List args, int index -> - def text = CS + String.format(body, args[0], args[1], index) + final HashSet res = new HashSet<>(); + final GroovyShell shell = new GroovyShell(); + for (int i = 0; i < arguments.size(); i++) { + List argument = arguments.get(i); + String text = CS + String.format(body, argument.get(0), argument.get(1), i); try { - shell.evaluate(text) + shell.evaluate(text); } catch (MultipleCompilationErrorsException ignored) { - res.add(index) + res.add(i); } } - - return res + return res; } } \ No newline at end of file