diff --git a/ChangeLog.md b/ChangeLog.md index fb8adaa4eef..b0970539833 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -354,6 +354,9 @@ These artifacts include extensions for the types available in the latter JDKs, s - [`KT-14197`](https://youtrack.jetbrains.com/issue/KT-14197) Move: Fix callable reference processing when moving to another package - [`KT-13781`](https://youtrack.jetbrains.com/issue/KT-13781) Extract Function: Do not wrap companion member references inside of the `with` call +##### New features +- [`KT-14792`](https://youtrack.jetbrains.com/issue/KT-14792) Rename: Suggest respective parameter name for the local variable passed to function + ## 1.0.5 ### IDE diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 3a75c70d6b5..f4664f80b37 100755 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -157,6 +157,7 @@ import org.jetbrains.kotlin.serialization.AbstractLocalClassProtoTest import org.jetbrains.kotlin.shortenRefs.AbstractShortenRefsTest import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlin.types.AbstractTypeBindingTest +import org.jetbrains.kotlin.idea.refactoring.AbstractNameSuggestionProviderTest import java.io.File import java.lang.IllegalArgumentException import java.util.* @@ -917,6 +918,10 @@ fun main(args: Array) { testClass { model("script/definition/navigation", extension = null, recursive = false) } + + testClass { + model("refactoring/nameSuggestionProvider") + } } testGroup("idea/idea-maven/test", "idea/idea-maven/testData") { diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinNameSuggestionProvider.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinNameSuggestionProvider.kt index 850b5517674..fae8e43a77d 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinNameSuggestionProvider.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/KotlinNameSuggestionProvider.kt @@ -20,15 +20,18 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiVariable import com.intellij.psi.codeStyle.JavaCodeStyleManager import com.intellij.psi.codeStyle.SuggestedNameInfo +import com.intellij.psi.search.LocalSearchScope +import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.statistics.JavaStatisticsManager import com.intellij.refactoring.rename.NameSuggestionProvider import org.jetbrains.kotlin.asJava.toLightElements import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor -import org.jetbrains.kotlin.psi.KtCallableDeclaration -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.utils.SmartList @@ -59,6 +62,17 @@ class KotlinNameSuggestionProvider : NameSuggestionProvider { } result += names + if (element is KtProperty && element.isLocal) { + for (ref in ReferencesSearch.search(element, LocalSearchScope(element.parent))) { + val refExpr = ref.element as? KtSimpleNameExpression ?: continue + val argument = refExpr.parent as? KtValueArgument ?: continue + val callElement = (argument.parent as? KtValueArgumentList)?.parent as? KtCallElement ?: continue + val resolvedCall = callElement.getResolvedCall(callElement.analyze(BodyResolveMode.PARTIAL)) ?: continue + val parameterName = (resolvedCall.getArgumentMapping(argument) as? ArgumentMatch)?.valueParameter?.name ?: continue + result += parameterName.asString() + } + } + return object : SuggestedNameInfo(names.toTypedArray()) { override fun nameChosen(name: String?) { val psiVariable = element.toLightElements().firstIsInstanceOrNull() ?: return diff --git a/idea/testData/refactoring/nameSuggestionProvider/localVarAsCallArgument.kt b/idea/testData/refactoring/nameSuggestionProvider/localVarAsCallArgument.kt new file mode 100644 index 00000000000..6baa8c4fa8f --- /dev/null +++ b/idea/testData/refactoring/nameSuggestionProvider/localVarAsCallArgument.kt @@ -0,0 +1,9 @@ +// SUGGESTED_NAMES: baz, paramBar, s +fun foo(paramBar: String) { + +} + +fun test() { + val baz = "" + foo(baz) +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/AbstractNameSuggestionProviderTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/AbstractNameSuggestionProviderTest.kt new file mode 100644 index 00000000000..fe1f1978656 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/AbstractNameSuggestionProviderTest.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * 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.jetbrains.kotlin.idea.refactoring + +import com.intellij.codeInsight.TargetElementUtil +import com.intellij.psi.PsiElement +import com.intellij.refactoring.rename.NameSuggestionProvider +import com.intellij.refactoring.rename.PreferrableNameSuggestionProvider +import junit.framework.TestCase +import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.idea.test.ProjectDescriptorWithStdlibSources +import org.jetbrains.kotlin.test.InTextDirectivesUtils + +abstract class AbstractNameSuggestionProviderTest : KotlinLightCodeInsightFixtureTestCase() { + private fun getSuggestNames(element: PsiElement): List { + val names = HashSet() + for (provider in NameSuggestionProvider.EP_NAME.extensions) { + val info = provider.getSuggestedNames(element, null, names) + if (info != null) { + if (provider is PreferrableNameSuggestionProvider && !provider.shouldCheckOthers()) break + } + } + return names.sorted() + } + + protected fun doTest(path: String) { + val file = myFixture.configureByFile(path) + val targetElement = TargetElementUtil.findTargetElement( + myFixture.editor, + TargetElementUtil.ELEMENT_NAME_ACCEPTED or TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED + )!! + val expectedNames = InTextDirectivesUtils.findListWithPrefixes(file.text, "// SUGGESTED_NAMES: ") + val actualNames = getSuggestNames(targetElement) + TestCase.assertEquals(expectedNames, actualNames) + } + + override fun getProjectDescriptor() = ProjectDescriptorWithStdlibSources.INSTANCE +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/NameSuggestionProviderTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/NameSuggestionProviderTestGenerated.java new file mode 100644 index 00000000000..186b0bd8911 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/NameSuggestionProviderTestGenerated.java @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * 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.jetbrains.kotlin.idea.refactoring; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/refactoring/nameSuggestionProvider") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class NameSuggestionProviderTestGenerated extends AbstractNameSuggestionProviderTest { + public void testAllFilesPresentInNameSuggestionProvider() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/nameSuggestionProvider"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("localVarAsCallArgument.kt") + public void testLocalVarAsCallArgument() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/nameSuggestionProvider/localVarAsCallArgument.kt"); + doTest(fileName); + } +}