diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/requests/CreateExecutableFromGroovyUsageRequest.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/requests/CreateExecutableFromGroovyUsageRequest.kt index 9c337e58fd8d..1b60800eb2b6 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/requests/CreateExecutableFromGroovyUsageRequest.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/requests/CreateExecutableFromGroovyUsageRequest.kt @@ -10,7 +10,7 @@ import com.intellij.psi.PsiJvmSubstitutor import com.intellij.psi.PsiType import com.intellij.psi.SmartPsiElementPointer import com.intellij.psi.codeStyle.JavaCodeStyleManager -import com.intellij.psi.codeStyle.VariableKind +import com.intellij.psi.codeStyle.VariableKind.PARAMETER import com.intellij.psi.util.createSmartPointer import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression @@ -18,6 +18,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousC import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil import org.jetbrains.plugins.groovy.lang.resolve.api.Argument import org.jetbrains.plugins.groovy.lang.resolve.api.ExpressionArgument +import kotlin.math.max +import kotlin.math.min internal abstract class CreateExecutableFromGroovyUsageRequest( call: T, @@ -29,7 +31,7 @@ internal abstract class CreateExecutableFromGroovyUsageRequest( private val callPointer: SmartPsiElementPointer = call.createSmartPointer(project) protected val call: T get() = callPointer.element ?: error("dead pointer") - abstract fun getArguments() : List? + abstract fun getArguments(): List? override fun isValid() = callPointer.element != null @@ -43,10 +45,14 @@ internal abstract class CreateExecutableFromGroovyUsageRequest( val argumentTypes = getArgumentTypes() ?: return emptyList() val codeStyleManager: JavaCodeStyleManager = project.service() - return argumentTypes.map {(type, _) -> - //if (expression != null) codeStyleManager.suggestSemanticNames(expression) //TODO add semantic names based on expression - val names = codeStyleManager.suggestNames(emptyList(), VariableKind.PARAMETER, type).names - expectedParameter(expectedTypes(type, ExpectedType.Kind.SUPERTYPE), names.toList()) + + val names = argumentTypes.map { (type, _) -> type to codeStyleManager.suggestNames(emptyList(), PARAMETER, type).names.toList() } + + val nameSupplier = ParametersNameSupplier(names) + + return names.map { (type, names) -> + //TODO add semantic names based on expression + expectedParameter(expectedTypes(type, ExpectedType.Kind.SUPERTYPE), names.map { nameSupplier.supplyName(it) }) } } @@ -67,4 +73,38 @@ internal abstract class CreateExecutableFromGroovyUsageRequest( } override fun getParameters() = getParameters(expectedParameters, project) + + private class ParametersNameSupplier(suggested: List>>) { + + private val namesCount = suggested + .flatMap { it.second } + .groupingBy { it } + .eachCount() + .mapValues { min(it.value - 1, 1) } + .toMutableMap() + + private val usedNames = mutableSetOf() + + fun supplyName(suggestion: String): String { + val usageCount = namesCount[suggestion] ?: return suggestion + if (usageCount == 0 && suggestion !in usedNames) { + usedNames.add(suggestion) + return suggestion + } + + val index = nextIndex(suggestion, usageCount) + val name = "$suggestion$index" + namesCount[suggestion] = index + 1 + usedNames.add(name) + return name + } + + private fun nextIndex(suggestion: String, start: Int): Int { + var index = max(start, 1) + while ("$suggestion$index" in usedNames) { + index++ + } + return index + } + } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/CreateMethodFromUsageTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/CreateMethodFromUsageTest.groovy index 22cd4c36c282..983ce2f62f61 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/CreateMethodFromUsageTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/fixes/CreateMethodFromUsageTest.groovy @@ -175,6 +175,18 @@ class CreateMethodFromUsageTest extends GrHighlightingTestBase { void testSuperConstructorInvocation() { doTest(CREATE_CONSTRUCTOR, 1, BEFORE) } + + void testSameParameterNames1() { + doTest() + } + + void testSameParameterNames2() { + doTest() + } + + void testSameParameterNames3() { + doTest() + } } diff --git a/plugins/groovy/testdata/fixes/createMethodFromUsage/generic/After.groovy b/plugins/groovy/testdata/fixes/createMethodFromUsage/generic/After.groovy index 6cf5c5e3c5b1..7c639c316154 100644 --- a/plugins/groovy/testdata/fixes/createMethodFromUsage/generic/After.groovy +++ b/plugins/groovy/testdata/fixes/createMethodFromUsage/generic/After.groovy @@ -1,5 +1,5 @@ class A { - def void bar(T t, T t) { + def void bar(T t1, T t2) { } } \ No newline at end of file diff --git a/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames1/After.groovy b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames1/After.groovy new file mode 100644 index 000000000000..82d9b02a80ee --- /dev/null +++ b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames1/After.groovy @@ -0,0 +1,5 @@ +class A { + void test(int integer1, int integer2, int integer3) { + + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames1/Before.groovy b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames1/Before.groovy new file mode 100644 index 000000000000..a7ca22abab45 --- /dev/null +++ b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames1/Before.groovy @@ -0,0 +1,2 @@ +class A { +} \ No newline at end of file diff --git a/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames1/script.groovy b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames1/script.groovy new file mode 100644 index 000000000000..0234325e79c8 --- /dev/null +++ b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames1/script.groovy @@ -0,0 +1 @@ +new A().test(1, 1, 1) \ No newline at end of file diff --git a/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames2/After.groovy b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames2/After.groovy new file mode 100644 index 000000000000..bcf632259fd6 --- /dev/null +++ b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames2/After.groovy @@ -0,0 +1,5 @@ +class A { + void test(int integer1, Integer1 integer11, int integer2) { + + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames2/Before.groovy b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames2/Before.groovy new file mode 100644 index 000000000000..a7ca22abab45 --- /dev/null +++ b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames2/Before.groovy @@ -0,0 +1,2 @@ +class A { +} \ No newline at end of file diff --git a/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames2/script.groovy b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames2/script.groovy new file mode 100644 index 000000000000..0a3f6ed225e1 --- /dev/null +++ b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames2/script.groovy @@ -0,0 +1,2 @@ +class Integer1 {} +new A().test(1, new Integer1(), 1) \ No newline at end of file diff --git a/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames3/After.groovy b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames3/After.groovy new file mode 100644 index 000000000000..773ed1aa4cb5 --- /dev/null +++ b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames3/After.groovy @@ -0,0 +1,5 @@ +class A { + void test(Integer1 integer1, int integer2, int integer3) { + + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames3/Before.groovy b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames3/Before.groovy new file mode 100644 index 000000000000..a7ca22abab45 --- /dev/null +++ b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames3/Before.groovy @@ -0,0 +1,2 @@ +class A { +} \ No newline at end of file diff --git a/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames3/script.groovy b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames3/script.groovy new file mode 100644 index 000000000000..c9ad2cd0992e --- /dev/null +++ b/plugins/groovy/testdata/fixes/createMethodFromUsage/sameParameterNames3/script.groovy @@ -0,0 +1,2 @@ +class Integer1 {} +new A().test(new Integer1(), 1, 1) \ No newline at end of file