From 3c94184de9e8c9e68f947f3190c1a497bee83208 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Mon, 24 Apr 2017 20:22:07 +0300 Subject: [PATCH] Rename: Support labeled expressions #KT-7107 Fixed --- .../kotlin/psi/KtLabeledExpression.java | 38 ++++++++++++- .../jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt | 13 ++++- .../kotlin/idea/references/referenceUtil.kt | 28 ++++++---- idea/src/META-INF/plugin.xml | 4 +- .../KotlinElementDescriptionProvider.kt | 1 + .../findUsages/KotlinFindUsagesProvider.kt | 1 + .../KotlinRefactoringSupportProvider.kt | 1 + .../idea/refactoring/dataContextUtils.kt | 24 +++++++++ ...tractReferenceSubstitutionRenameHandler.kt | 27 ++++------ ...abeledReferenceInLambdaArgumentHandler.kt} | 21 ++++++-- ...sByCompanionObjectShortReferenceHandler.kt | 11 ++-- .../RenameJavaSyntheticPropertyHandler.kt | 14 +++-- .../KotlinTargetElementEvaluator.kt | 25 +++++++-- .../labeledAnonymousFunByLabel/after/test.kt | 5 ++ .../labeledAnonymousFunByLabel/before/test.kt | 5 ++ .../labeledLambdaByLabel.test | 5 ++ .../rename/labeledLambdaByLabel/after/test.kt | 5 ++ .../labeledLambdaByLabel/before/test.kt | 5 ++ .../labeledLambdaByLabel.test | 5 ++ .../labeledLambdaByLabelRef/after/test.kt | 5 ++ .../labeledLambdaByLabelRef/before/test.kt | 5 ++ .../labeledLambdaByLabelRef.test | 5 ++ .../after/test.kt | 5 ++ .../before/test.kt | 5 ++ .../labeledLambdaByLabelWithParens.test | 5 ++ .../after/test.kt | 5 ++ .../before/test.kt | 5 ++ .../labeledLambdaByLabelWithSameName.test | 5 ++ .../after/test.kt | 5 ++ .../before/test.kt | 5 ++ .../labeledLambdaWithMultipleLabels.test | 5 ++ .../rename/labeledLoopByLabel/after/test.kt | 6 +++ .../rename/labeledLoopByLabel/before/test.kt | 6 +++ .../labeledLoopByLabel.test | 5 ++ .../after/test.kt | 6 +++ .../before/test.kt | 6 +++ .../labeledLoopByLabelRefInBreak.test | 5 ++ .../after/test.kt | 6 +++ .../before/test.kt | 6 +++ .../labeledLoopByLabelRefInContinue.test | 5 ++ .../usageHighlighter/labeledAnonymousFun.kt | 5 ++ .../usageHighlighter/labeledLambda.kt | 5 ++ idea/testData/usageHighlighter/labeledLoop.kt | 6 +++ .../UsageHighlightingTestGenerated.java | 18 +++++++ .../refactoring/rename/AbstractRenameTest.kt | 10 +++- .../rename/RenameTestGenerated.java | 54 +++++++++++++++++++ 46 files changed, 395 insertions(+), 52 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/refactoring/dataContextUtils.kt rename idea/src/org/jetbrains/kotlin/idea/refactoring/rename/{RenameFunctionByLabeledReferenceInLambdaArgumentHandler.kt => RenameByLabeledReferenceInLambdaArgumentHandler.kt} (57%) create mode 100644 idea/testData/refactoring/rename/labeledAnonymousFunByLabel/after/test.kt create mode 100644 idea/testData/refactoring/rename/labeledAnonymousFunByLabel/before/test.kt create mode 100644 idea/testData/refactoring/rename/labeledAnonymousFunByLabel/labeledLambdaByLabel.test create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabel/after/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabel/before/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabel/labeledLambdaByLabel.test create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabelRef/after/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabelRef/before/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabelRef/labeledLambdaByLabelRef.test create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/after/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/before/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/labeledLambdaByLabelWithParens.test create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/after/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/before/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/labeledLambdaByLabelWithSameName.test create mode 100644 idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/after/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/before/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/labeledLambdaWithMultipleLabels.test create mode 100644 idea/testData/refactoring/rename/labeledLoopByLabel/after/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLoopByLabel/before/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLoopByLabel/labeledLoopByLabel.test create mode 100644 idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/after/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/before/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/labeledLoopByLabelRefInBreak.test create mode 100644 idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/after/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/before/test.kt create mode 100644 idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/labeledLoopByLabelRefInContinue.test create mode 100644 idea/testData/usageHighlighter/labeledAnonymousFun.kt create mode 100644 idea/testData/usageHighlighter/labeledLambda.kt create mode 100644 idea/testData/usageHighlighter/labeledLoop.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLabeledExpression.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLabeledExpression.java index f7e95987c34..a9a12ce9d6a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLabeledExpression.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtLabeledExpression.java @@ -17,11 +17,15 @@ package org.jetbrains.kotlin.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNameIdentifierOwner; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.SearchScope; +import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class KtLabeledExpression extends KtExpressionWithLabel { - +public class KtLabeledExpression extends KtExpressionWithLabel implements PsiNameIdentifierOwner { public KtLabeledExpression(@NotNull ASTNode node) { super(node); } @@ -35,4 +39,34 @@ public class KtLabeledExpression extends KtExpressionWithLabel { public R accept(@NotNull KtVisitor visitor, D data) { return visitor.visitLabeledExpression(this, data); } + + @Override + public String getName() { + return getLabelName(); + } + + @Override + public PsiElement setName(@NotNull String name) throws IncorrectOperationException { + KtSimpleNameExpression currentLabel = getTargetLabel(); + if (currentLabel != null) { + KtSimpleNameExpression newLabel = new KtPsiFactory(getProject()).createLabeledExpression(name).getTargetLabel(); + //noinspection ConstantConditions + currentLabel.replace(newLabel); + } + return this; + } + + @Nullable + @Override + public PsiElement getNameIdentifier() { + KtSimpleNameExpression targetLabel = getTargetLabel(); + if (targetLabel == null) return null; + return targetLabel.getIdentifier(); + } + + @NotNull + @Override + public SearchScope getUseScope() { + return new LocalSearchScope(this); + } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt index ca7b4f279ca..2828669308c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt @@ -536,4 +536,15 @@ fun KtDeclaration.hasBody() = when (this) { fun KtExpression.referenceExpression(): KtReferenceExpression? = - (if (this is KtCallExpression) calleeExpression else this) as? KtReferenceExpression \ No newline at end of file + (if (this is KtCallExpression) calleeExpression else this) as? KtReferenceExpression + +fun KtExpression.getLabeledParent(labelName: String): KtLabeledExpression? { + parents.forEach { + when (it) { + is KtLabeledExpression -> if (it.getLabelName() == labelName) return it + is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLambdaExpression -> return@forEach + else -> return null + } + } + return null +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/referenceUtil.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/referenceUtil.kt index 005c2b9ef01..cdad154089d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/referenceUtil.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/referenceUtil.kt @@ -30,10 +30,7 @@ import org.jetbrains.kotlin.idea.util.ProjectRootsUtil import org.jetbrains.kotlin.kdoc.psi.impl.KDocName import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS -import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType -import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch -import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis +import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension @@ -98,12 +95,25 @@ fun PsiReference.matchesTarget(candidateTarget: PsiElement): Boolean { return true } - if (element is KtLabelReferenceExpression && (element.parent as? KtContainerNode)?.parent is KtReturnExpression) { - targets.forEach { - if (it !is KtFunctionLiteral && !(it is KtNamedFunction && it.name.isNullOrEmpty())) return@forEach + val element = element + if (element is KtLabelReferenceExpression) { + val labelParent = (element.parent as? KtContainerNode)?.parent + when (labelParent) { + is KtReturnExpression -> targets.forEach { + if (it !is KtFunctionLiteral && !(it is KtNamedFunction && it.name.isNullOrEmpty())) return@forEach + it as KtFunction - val calleeReference = (it as KtFunction).getCalleeByLambdaArgument()?.mainReference ?: return@forEach - if (calleeReference.matchesTarget(candidateTarget)) return true + val labeledExpression = it.getLabeledParent(element.getReferencedName()) + if (labeledExpression != null) { + if (candidateTarget == labeledExpression) return true else return@forEach + } + val calleeReference = it.getCalleeByLambdaArgument()?.mainReference ?: return@forEach + if (calleeReference.matchesTarget(candidateTarget)) return true + } + is KtBreakExpression, is KtContinueExpression -> targets.forEach { + val labeledExpression = (it as? KtExpression)?.getLabeledParent(element.getReferencedName()) ?: return@forEach + if (candidateTarget == labeledExpression) return true + } } } diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 99021731cff..a249e905ec3 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -497,7 +497,7 @@ - + @@ -755,6 +755,8 @@ language="kotlin" implementationClass="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinTargetElementEvaluator" /> + + diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt index 1e8e295cf36..94092398016 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinElementDescriptionProvider.kt @@ -124,6 +124,7 @@ class KotlinElementDescriptionProvider : ElementDescriptionProvider { is KtParameter -> "parameter" is KtDestructuringDeclarationEntry -> "variable" is KtTypeAlias -> "type alias" + is KtLabeledExpression -> "label" is RenameJavaSyntheticPropertyHandler.SyntheticPropertyWrapper -> "property" is KtLightClassForFacade -> "facade class" is RenameKotlinPropertyProcessor.PropertyMethodWrapper -> "property accessor" diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt index f2c9fa92689..bf504086b2d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesProvider.kt @@ -79,6 +79,7 @@ class KotlinFindUsagesProvider : FindUsagesProvider { val funDescription = "$name$paramsDescription" + (returnTypeDescription?.let { ": $it" } ?: "") return funDescription + (element.containerDescription?.let { " of $it" } ?: "") } + is KtLabeledExpression -> element.getLabelName() ?: "" is KtLightElement<*, *> -> element.kotlinOrigin?.let { getDescriptiveName(it) } ?: "" else -> "" } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinRefactoringSupportProvider.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinRefactoringSupportProvider.kt index c31dcf39db1..b8b296b4ffb 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinRefactoringSupportProvider.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinRefactoringSupportProvider.kt @@ -71,6 +71,7 @@ class KotlinRefactoringSupportProvider : RefactoringSupportProvider() { return grandparent is KtCatchClause || grandparent is KtFunctionLiteral } } + is KtLabeledExpression -> return true } return false } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/dataContextUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/dataContextUtils.kt new file mode 100644 index 00000000000..38246fd55b0 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/dataContextUtils.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2010-2017 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.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.project.Project + +val DataContext.project: Project + get() = CommonDataKeys.PROJECT.getData(this)!! diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/AbstractReferenceSubstitutionRenameHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/AbstractReferenceSubstitutionRenameHandler.kt index 41c3feab6c8..2859706fc03 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/AbstractReferenceSubstitutionRenameHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/AbstractReferenceSubstitutionRenameHandler.kt @@ -25,18 +25,17 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiWhiteSpace import com.intellij.refactoring.rename.PsiElementRenameHandler +import com.intellij.refactoring.rename.RenameHandler import com.intellij.refactoring.rename.inplace.MemberInplaceRenameHandler -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils -import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType -abstract class AbstractReferenceSubstitutionRenameHandler : PsiElementRenameHandler() { - private val inplaceRenameHandler = MemberInplaceRenameHandler() - - protected fun getReferenceExpression(dataContext: DataContext): KtSimpleNameExpression? { +abstract class AbstractReferenceSubstitutionRenameHandler( + private val delegateHandler: RenameHandler = MemberInplaceRenameHandler() +) : PsiElementRenameHandler() { + protected fun getReferenceExpression(dataContext: DataContext): KtSimpleNameExpression? { val caret = CommonDataKeys.CARET.getData(dataContext) ?: return null val ktFile = CommonDataKeys.PSI_FILE.getData(dataContext) as? KtFile ?: return null var elementAtCaret = ktFile.findElementAt(caret.offset) @@ -46,25 +45,21 @@ abstract class AbstractReferenceSubstitutionRenameHandler() } - protected abstract fun getTargetDescriptor(dataContext: DataContext): D? - - protected open fun getElementToRename(project: Project, descriptor: D): PsiElement? { - return DescriptorToSourceUtilsIde.getAnyDeclaration(project, descriptor) - } + protected abstract fun getElementToRename(dataContext: DataContext): PsiElement? override fun isAvailableOnDataContext(dataContext: DataContext): Boolean { - return CommonDataKeys.EDITOR.getData(dataContext) != null && getTargetDescriptor(dataContext) != null + return CommonDataKeys.EDITOR.getData(dataContext) != null && getElementToRename(dataContext) != null } override fun invoke(project: Project, editor: Editor?, file: PsiFile?, dataContext: DataContext) { - val descriptor = getTargetDescriptor(dataContext) ?: return + val elementToRename = getElementToRename(dataContext) ?: return val wrappingContext = DataContext { id -> - if (CommonDataKeys.PSI_ELEMENT.`is`(id)) return@DataContext getElementToRename(project, descriptor) + if (CommonDataKeys.PSI_ELEMENT.`is`(id)) return@DataContext elementToRename dataContext.getData(id) } // Can't provide new name for inplace refactoring in unit test mode - if (!ApplicationManager.getApplication().isUnitTestMode && inplaceRenameHandler.isAvailableOnDataContext(wrappingContext)) { - inplaceRenameHandler.invoke(project, editor, file, wrappingContext) + if (!ApplicationManager.getApplication().isUnitTestMode && delegateHandler.isAvailableOnDataContext(wrappingContext)) { + delegateHandler.invoke(project, editor, file, wrappingContext) } else { super.invoke(project, editor, file, wrappingContext) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameFunctionByLabeledReferenceInLambdaArgumentHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameByLabeledReferenceInLambdaArgumentHandler.kt similarity index 57% rename from idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameFunctionByLabeledReferenceInLambdaArgumentHandler.kt rename to idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameByLabeledReferenceInLambdaArgumentHandler.kt index 9f120f4b9ca..b988caed4fd 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameFunctionByLabeledReferenceInLambdaArgumentHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameByLabeledReferenceInLambdaArgumentHandler.kt @@ -17,20 +17,33 @@ package org.jetbrains.kotlin.idea.refactoring.rename import com.intellij.openapi.actionSystem.DataContext +import com.intellij.psi.PsiElement +import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde +import org.jetbrains.kotlin.idea.refactoring.project import org.jetbrains.kotlin.idea.references.getCalleeByLambdaArgument import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtLabelReferenceExpression +import org.jetbrains.kotlin.psi.psiUtil.getLabeledParent import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -class RenameFunctionByLabeledReferenceInLambdaArgumentHandler : AbstractReferenceSubstitutionRenameHandler() { - override fun getTargetDescriptor(dataContext: DataContext): FunctionDescriptor? { +class RenameByLabeledReferenceInLambdaArgumentHandler : + AbstractReferenceSubstitutionRenameHandler(VariableInplaceRenameHandler()) { + override fun getElementToRename(dataContext: DataContext): PsiElement? { val refExpr = getReferenceExpression(dataContext) as? KtLabelReferenceExpression ?: return null val context = refExpr.analyze(BodyResolveMode.PARTIAL) val lambda = context[BindingContext.LABEL_TARGET, refExpr] as? KtFunction ?: return null - val calleeExpression = lambda.getCalleeByLambdaArgument() ?: return null - return context[BindingContext.REFERENCE_TARGET, calleeExpression] as? FunctionDescriptor + val labeledParent = lambda.getLabeledParent(refExpr.getReferencedName()) + return if (labeledParent != null) { + labeledParent + } + else { + val calleeExpression = lambda.getCalleeByLambdaArgument() ?: return null + val descriptor = context[BindingContext.REFERENCE_TARGET, calleeExpression] as? FunctionDescriptor ?: return null + DescriptorToSourceUtilsIde.getAnyDeclaration(dataContext.project, descriptor) + } } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameClassByCompanionObjectShortReferenceHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameClassByCompanionObjectShortReferenceHandler.kt index d2fc0b712be..5d1ba405e0e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameClassByCompanionObjectShortReferenceHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameClassByCompanionObjectShortReferenceHandler.kt @@ -17,14 +17,17 @@ package org.jetbrains.kotlin.idea.refactoring.rename import com.intellij.openapi.actionSystem.DataContext -import org.jetbrains.kotlin.descriptors.ClassifierDescriptor +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde +import org.jetbrains.kotlin.idea.refactoring.project import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -class RenameClassByCompanionObjectShortReferenceHandler : AbstractReferenceSubstitutionRenameHandler() { - override fun getTargetDescriptor(dataContext: DataContext): ClassifierDescriptor? { +class RenameClassByCompanionObjectShortReferenceHandler : AbstractReferenceSubstitutionRenameHandler() { + override fun getElementToRename(dataContext: DataContext): PsiElement? { val refExpr = getReferenceExpression(dataContext) ?: return null - return refExpr.analyze(BodyResolveMode.PARTIAL)[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, refExpr] + val descriptor = refExpr.analyze(BodyResolveMode.PARTIAL)[BindingContext.SHORT_REFERENCE_TO_COMPANION_OBJECT, refExpr] ?: return null + return DescriptorToSourceUtilsIde.getAnyDeclaration(dataContext.project, descriptor) } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameJavaSyntheticPropertyHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameJavaSyntheticPropertyHandler.kt index 9ed37119039..06ec7eed098 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameJavaSyntheticPropertyHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameJavaSyntheticPropertyHandler.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.idea.refactoring.rename import com.intellij.openapi.actionSystem.DataContext -import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import com.intellij.psi.PsiManager import com.intellij.psi.PsiMethod @@ -27,6 +26,7 @@ import com.intellij.psi.search.SearchScope import com.intellij.refactoring.rename.RenamePsiElementProcessor import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.refactoring.project import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.resolve.BindingContext @@ -34,7 +34,7 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor -class RenameJavaSyntheticPropertyHandler : AbstractReferenceSubstitutionRenameHandler() { +class RenameJavaSyntheticPropertyHandler : AbstractReferenceSubstitutionRenameHandler() { class Processor : RenamePsiElementProcessor() { override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap, scope: SearchScope) { val propertyWrapper = element as? SyntheticPropertyWrapper ?: return @@ -68,12 +68,10 @@ class RenameJavaSyntheticPropertyHandler : AbstractReferenceSubstitutionRenameHa } } - override fun getTargetDescriptor(dataContext: DataContext): SyntheticJavaPropertyDescriptor? { + override fun getElementToRename(dataContext: DataContext): PsiElement? { val refExpr = getReferenceExpression(dataContext) ?: return null - return refExpr.analyze(BodyResolveMode.PARTIAL)[BindingContext.REFERENCE_TARGET, refExpr] as? SyntheticJavaPropertyDescriptor - } - - override fun getElementToRename(project: Project, descriptor: SyntheticJavaPropertyDescriptor): PsiElement? { - return SyntheticPropertyWrapper(PsiManager.getInstance(project), descriptor) + val descriptor = refExpr.analyze(BodyResolveMode.PARTIAL)[BindingContext.REFERENCE_TARGET, refExpr] as? SyntheticJavaPropertyDescriptor + ?: return null + return SyntheticPropertyWrapper(PsiManager.getInstance(dataContext.project), descriptor) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt index 3bcde7d242c..f73cee7b8ef 100644 --- a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt +++ b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinTargetElementEvaluator.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.idea.search.ideaExtensions import com.intellij.codeInsight.JavaTargetElementEvaluator import com.intellij.codeInsight.TargetElementEvaluatorEx import com.intellij.codeInsight.TargetElementUtil +import com.intellij.codeInsight.TargetElementUtilExtender import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.PsiReference @@ -27,17 +28,17 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource import org.jetbrains.kotlin.idea.intentions.isAutoCreatedItUsage import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference +import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject -import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType -import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch -import org.jetbrains.kotlin.psi.psiUtil.isAbstract +import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.source.getPsi -class KotlinTargetElementEvaluator : TargetElementEvaluatorEx { +class KotlinTargetElementEvaluator : TargetElementEvaluatorEx, TargetElementUtilExtender { companion object { + val DO_NOT_UNWRAP_LABELED_EXPRESSION = 0x100 + // Place caret after the open curly brace in lambda for generated 'it' fun findLambdaOpenLBraceForGeneratedIt(ref: PsiReference): PsiElement? { val element: PsiElement = ref.element @@ -66,9 +67,23 @@ class KotlinTargetElementEvaluator : TargetElementEvaluatorEx { } } + override fun getAdditionalDefinitionSearchFlags() = 0 + + override fun getAdditionalReferenceSearchFlags() = DO_NOT_UNWRAP_LABELED_EXPRESSION + + override fun getAllAdditionalFlags() = DO_NOT_UNWRAP_LABELED_EXPRESSION + override fun includeSelfInGotoImplementation(element: PsiElement): Boolean = !(element is KtClass && element.isAbstract()) override fun getElementByReference(ref: PsiReference, flags: Int): PsiElement? { + if (ref is KtSimpleNameReference && ref.expression is KtLabelReferenceExpression) { + val refTarget = ref.resolve() as? KtExpression ?: return null + if (!BitUtil.isSet(flags, DO_NOT_UNWRAP_LABELED_EXPRESSION)) { + return refTarget.getLabeledParent(ref.expression.getReferencedName()) ?: refTarget + } + return refTarget + } + // prefer destructing declaration entry to its target if element name is accepted if (ref is KtDestructuringDeclarationReference && BitUtil.isSet(flags, TargetElementUtil.ELEMENT_NAME_ACCEPTED)) { return ref.element diff --git a/idea/testData/refactoring/rename/labeledAnonymousFunByLabel/after/test.kt b/idea/testData/refactoring/rename/labeledAnonymousFunByLabel/after/test.kt new file mode 100644 index 00000000000..bc15594fb3b --- /dev/null +++ b/idea/testData/refactoring/rename/labeledAnonymousFunByLabel/after/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo (baz@ fun(): Boolean { return@baz false }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledAnonymousFunByLabel/before/test.kt b/idea/testData/refactoring/rename/labeledAnonymousFunByLabel/before/test.kt new file mode 100644 index 00000000000..9a60add57f1 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledAnonymousFunByLabel/before/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo (/*rename*/bar@ fun(): Boolean { return@bar false }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledAnonymousFunByLabel/labeledLambdaByLabel.test b/idea/testData/refactoring/rename/labeledAnonymousFunByLabel/labeledLambdaByLabel.test new file mode 100644 index 00000000000..8d20735c082 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledAnonymousFunByLabel/labeledLambdaByLabel.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "baz" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabel/after/test.kt b/idea/testData/refactoring/rename/labeledLambdaByLabel/after/test.kt new file mode 100644 index 00000000000..08f14de44f2 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabel/after/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo baz@ { return@baz false } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabel/before/test.kt b/idea/testData/refactoring/rename/labeledLambdaByLabel/before/test.kt new file mode 100644 index 00000000000..a9c0db9d722 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabel/before/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo /*rename*/bar@ { return@bar false } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabel/labeledLambdaByLabel.test b/idea/testData/refactoring/rename/labeledLambdaByLabel/labeledLambdaByLabel.test new file mode 100644 index 00000000000..8d20735c082 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabel/labeledLambdaByLabel.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "baz" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabelRef/after/test.kt b/idea/testData/refactoring/rename/labeledLambdaByLabelRef/after/test.kt new file mode 100644 index 00000000000..08f14de44f2 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabelRef/after/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo baz@ { return@baz false } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabelRef/before/test.kt b/idea/testData/refactoring/rename/labeledLambdaByLabelRef/before/test.kt new file mode 100644 index 00000000000..747303f5671 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabelRef/before/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo bar@ { return@/*rename*/bar false } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabelRef/labeledLambdaByLabelRef.test b/idea/testData/refactoring/rename/labeledLambdaByLabelRef/labeledLambdaByLabelRef.test new file mode 100644 index 00000000000..dae046abfe1 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabelRef/labeledLambdaByLabelRef.test @@ -0,0 +1,5 @@ +{ + "type": "AUTO_DETECT", + "mainFile": "test.kt", + "newName": "baz" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/after/test.kt b/idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/after/test.kt new file mode 100644 index 00000000000..501f176699f --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/after/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo (baz@ { return@baz false }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/before/test.kt b/idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/before/test.kt new file mode 100644 index 00000000000..417d5c29591 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/before/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo (/*rename*/bar@ { return@bar false }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/labeledLambdaByLabelWithParens.test b/idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/labeledLambdaByLabelWithParens.test new file mode 100644 index 00000000000..8d20735c082 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/labeledLambdaByLabelWithParens.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "baz" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/after/test.kt b/idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/after/test.kt new file mode 100644 index 00000000000..08f14de44f2 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/after/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo baz@ { return@baz false } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/before/test.kt b/idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/before/test.kt new file mode 100644 index 00000000000..22346c41449 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/before/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo /*rename*/foo@ { return@foo false } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/labeledLambdaByLabelWithSameName.test b/idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/labeledLambdaByLabelWithSameName.test new file mode 100644 index 00000000000..8d20735c082 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/labeledLambdaByLabelWithSameName.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "baz" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/after/test.kt b/idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/after/test.kt new file mode 100644 index 00000000000..be53b922b83 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/after/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo (bar2@ baz@ { return@baz false }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/before/test.kt b/idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/before/test.kt new file mode 100644 index 00000000000..e6485af0007 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/before/test.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo (bar2@ /*rename*/bar@ { return@bar false }) +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/labeledLambdaWithMultipleLabels.test b/idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/labeledLambdaWithMultipleLabels.test new file mode 100644 index 00000000000..8d20735c082 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/labeledLambdaWithMultipleLabels.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "baz" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLoopByLabel/after/test.kt b/idea/testData/refactoring/rename/labeledLoopByLabel/after/test.kt new file mode 100644 index 00000000000..55b1fd35bb0 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLoopByLabel/after/test.kt @@ -0,0 +1,6 @@ +fun test() { + bar@ for (n in 1..10) { + if (n == 5) continue@bar + if (n > 8) break@bar + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLoopByLabel/before/test.kt b/idea/testData/refactoring/rename/labeledLoopByLabel/before/test.kt new file mode 100644 index 00000000000..6457001277d --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLoopByLabel/before/test.kt @@ -0,0 +1,6 @@ +fun test() { + /*rename*/foo@ for (n in 1..10) { + if (n == 5) continue@foo + if (n > 8) break@foo + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLoopByLabel/labeledLoopByLabel.test b/idea/testData/refactoring/rename/labeledLoopByLabel/labeledLoopByLabel.test new file mode 100644 index 00000000000..9e08b548cbd --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLoopByLabel/labeledLoopByLabel.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "bar" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/after/test.kt b/idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/after/test.kt new file mode 100644 index 00000000000..55b1fd35bb0 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/after/test.kt @@ -0,0 +1,6 @@ +fun test() { + bar@ for (n in 1..10) { + if (n == 5) continue@bar + if (n > 8) break@bar + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/before/test.kt b/idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/before/test.kt new file mode 100644 index 00000000000..ae9781731cb --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/before/test.kt @@ -0,0 +1,6 @@ +fun test() { + foo@ for (n in 1..10) { + if (n == 5) continue@foo + if (n > 8) break@/*rename*/foo + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/labeledLoopByLabelRefInBreak.test b/idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/labeledLoopByLabelRefInBreak.test new file mode 100644 index 00000000000..9e08b548cbd --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/labeledLoopByLabelRefInBreak.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "bar" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/after/test.kt b/idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/after/test.kt new file mode 100644 index 00000000000..55b1fd35bb0 --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/after/test.kt @@ -0,0 +1,6 @@ +fun test() { + bar@ for (n in 1..10) { + if (n == 5) continue@bar + if (n > 8) break@bar + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/before/test.kt b/idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/before/test.kt new file mode 100644 index 00000000000..bfeda481e1e --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/before/test.kt @@ -0,0 +1,6 @@ +fun test() { + foo@ for (n in 1..10) { + if (n == 5) continue@/*rename*/foo + if (n > 8) break@foo + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/labeledLoopByLabelRefInContinue.test b/idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/labeledLoopByLabelRefInContinue.test new file mode 100644 index 00000000000..9e08b548cbd --- /dev/null +++ b/idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/labeledLoopByLabelRefInContinue.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "bar" +} \ No newline at end of file diff --git a/idea/testData/usageHighlighter/labeledAnonymousFun.kt b/idea/testData/usageHighlighter/labeledAnonymousFun.kt new file mode 100644 index 00000000000..2709d299e19 --- /dev/null +++ b/idea/testData/usageHighlighter/labeledAnonymousFun.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo (~bar@ fun(): Boolean { return@bar false }) +} \ No newline at end of file diff --git a/idea/testData/usageHighlighter/labeledLambda.kt b/idea/testData/usageHighlighter/labeledLambda.kt new file mode 100644 index 00000000000..d861937a7a1 --- /dev/null +++ b/idea/testData/usageHighlighter/labeledLambda.kt @@ -0,0 +1,5 @@ +fun foo(f: () -> R) = f() + +fun test() { + foo ~bar@ { return@bar false } +} \ No newline at end of file diff --git a/idea/testData/usageHighlighter/labeledLoop.kt b/idea/testData/usageHighlighter/labeledLoop.kt new file mode 100644 index 00000000000..08bff4ed5be --- /dev/null +++ b/idea/testData/usageHighlighter/labeledLoop.kt @@ -0,0 +1,6 @@ +fun test() { + ~foo@ for (n in 1..10) { + if (n == 5) continue@foo + if (n > 8) break@foo + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/highlighter/UsageHighlightingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/highlighter/UsageHighlightingTestGenerated.java index 999b361ebdc..87f05a87bd5 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/highlighter/UsageHighlightingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/highlighter/UsageHighlightingTestGenerated.java @@ -36,6 +36,24 @@ public class UsageHighlightingTestGenerated extends AbstractUsageHighlightingTes KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/usageHighlighter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true); } + @TestMetadata("labeledAnonymousFun.kt") + public void testLabeledAnonymousFun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/usageHighlighter/labeledAnonymousFun.kt"); + doTest(fileName); + } + + @TestMetadata("labeledLambda.kt") + public void testLabeledLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/usageHighlighter/labeledLambda.kt"); + doTest(fileName); + } + + @TestMetadata("labeledLoop.kt") + public void testLabeledLoop() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/usageHighlighter/labeledLoop.kt"); + doTest(fileName); + } + @TestMetadata("localVal.kt") public void testLocalVal() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/usageHighlighter/localVal.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt index b0af01a446b..e6f6f4b0edc 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt @@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.editor.EditorFactory import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider import com.intellij.openapi.module.Module import com.intellij.openapi.project.Project import com.intellij.openapi.roots.ModuleRootManager @@ -333,12 +334,17 @@ abstract class AbstractRenameTest : KotlinLightCodeInsightFixtureTestCase() { assert(marker != -1) editor.caretModel.moveToOffset(marker) + val currentCaret = editor.caretModel.currentCaret + + val textEditorPsiDataProvider = TextEditorPsiDataProvider() val dataContext = DataContext { dataId -> when (dataId) { + CommonDataKeys.PROJECT.name -> project CommonDataKeys.EDITOR.name -> editor - CommonDataKeys.CARET.name -> editor.caretModel.currentCaret - CommonDataKeys.PSI_FILE.name -> psiFile + CommonDataKeys.CARET.name, + CommonDataKeys.PSI_ELEMENT.name, + CommonDataKeys.PSI_FILE.name -> textEditorPsiDataProvider.getData(dataId, editor, currentCaret) PsiElementRenameHandler.DEFAULT_NAME.name -> newName else -> null } diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java index cf0da056a2f..76f9e90a48a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java @@ -204,6 +204,60 @@ public class RenameTestGenerated extends AbstractRenameTest { doTest(fileName); } + @TestMetadata("labeledAnonymousFunByLabel/labeledLambdaByLabel.test") + public void testLabeledAnonymousFunByLabel_LabeledLambdaByLabel() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledAnonymousFunByLabel/labeledLambdaByLabel.test"); + doTest(fileName); + } + + @TestMetadata("labeledLambdaByLabel/labeledLambdaByLabel.test") + public void testLabeledLambdaByLabel_LabeledLambdaByLabel() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledLambdaByLabel/labeledLambdaByLabel.test"); + doTest(fileName); + } + + @TestMetadata("labeledLambdaByLabelRef/labeledLambdaByLabelRef.test") + public void testLabeledLambdaByLabelRef_LabeledLambdaByLabelRef() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledLambdaByLabelRef/labeledLambdaByLabelRef.test"); + doTest(fileName); + } + + @TestMetadata("labeledLambdaByLabelWithParens/labeledLambdaByLabelWithParens.test") + public void testLabeledLambdaByLabelWithParens_LabeledLambdaByLabelWithParens() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledLambdaByLabelWithParens/labeledLambdaByLabelWithParens.test"); + doTest(fileName); + } + + @TestMetadata("labeledLambdaByLabelWithSameName/labeledLambdaByLabelWithSameName.test") + public void testLabeledLambdaByLabelWithSameName_LabeledLambdaByLabelWithSameName() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledLambdaByLabelWithSameName/labeledLambdaByLabelWithSameName.test"); + doTest(fileName); + } + + @TestMetadata("labeledLambdaWithMultipleLabels/labeledLambdaWithMultipleLabels.test") + public void testLabeledLambdaWithMultipleLabels_LabeledLambdaWithMultipleLabels() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledLambdaWithMultipleLabels/labeledLambdaWithMultipleLabels.test"); + doTest(fileName); + } + + @TestMetadata("labeledLoopByLabel/labeledLoopByLabel.test") + public void testLabeledLoopByLabel_LabeledLoopByLabel() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledLoopByLabel/labeledLoopByLabel.test"); + doTest(fileName); + } + + @TestMetadata("labeledLoopByLabelRefInBreak/labeledLoopByLabelRefInBreak.test") + public void testLabeledLoopByLabelRefInBreak_LabeledLoopByLabelRefInBreak() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledLoopByLabelRefInBreak/labeledLoopByLabelRefInBreak.test"); + doTest(fileName); + } + + @TestMetadata("labeledLoopByLabelRefInContinue/labeledLoopByLabelRefInContinue.test") + public void testLabeledLoopByLabelRefInContinue_LabeledLoopByLabelRefInContinue() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledLoopByLabelRefInContinue/labeledLoopByLabelRefInContinue.test"); + doTest(fileName); + } + @TestMetadata("labeledReturnInAnonymousFun/labeledReturnInAnonymousFun.test") public void testLabeledReturnInAnonymousFun_LabeledReturnInAnonymousFun() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/labeledReturnInAnonymousFun/labeledReturnInAnonymousFun.test");