diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/moveConflictUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/moveConflictUtils.kt index c84357638fd..e624356b4ca 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/moveConflictUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/moveConflictUtils.kt @@ -42,11 +42,11 @@ import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.project.forcedTargetPlatform import org.jetbrains.kotlin.idea.refactoring.getUsageContext import org.jetbrains.kotlin.idea.refactoring.move.KotlinMoveUsage +import org.jetbrains.kotlin.idea.refactoring.pullUp.renderForConflicts import org.jetbrains.kotlin.idea.search.and import org.jetbrains.kotlin.idea.search.not import org.jetbrains.kotlin.idea.util.projectStructure.getModule import org.jetbrains.kotlin.idea.util.projectStructure.module -import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.name.FqName @@ -191,8 +191,10 @@ class MoveConflictChecker( private fun render(declaration: PsiElement) = RefactoringUIUtil.getDescription(declaration, false) + private fun render(descriptor: DeclarationDescriptor) = CommonRefactoringUtil.htmlEmphasize(descriptor.renderForConflicts()) + // Based on RefactoringConflictsUtil.analyzeModuleConflicts - fun analyzeModuleConflictsInUsages( + private fun analyzeModuleConflictsInUsages( project: Project, usages: Collection, targetScope: VirtualFile, @@ -231,7 +233,7 @@ class MoveConflictChecker( } } - fun checkModuleConflictsInUsages(externalUsages: MutableSet, conflicts: MultiMap) { + private fun checkModuleConflictsInUsages(externalUsages: MutableSet, conflicts: MultiMap) { val newConflicts = MultiMap() val targetScope = moveTarget.targetScope ?: return @@ -363,7 +365,7 @@ class MoveConflictChecker( internalUsages.removeIf { it.reference?.element?.let { element -> element in referencesToSkip } ?: false } } - fun checkVisibilityInUsages(usages: Collection, conflicts: MultiMap) { + private fun checkVisibilityInUsages(usages: Collection, conflicts: MultiMap) { val declarationToContainers = HashMap>() for (usage in usages) { val element = usage.element @@ -578,12 +580,14 @@ class MoveConflictChecker( fun walkDeclarations( currentScopeDeclaration: DeclarationDescriptor, declaration: DeclarationDescriptor, - report: (String, String) -> Unit + report: (DeclarationDescriptor, DeclarationDescriptor) -> Unit ) { - fun descrText(d: DeclarationDescriptor) = d.findPsi()?.text ?: "unknown" when (currentScopeDeclaration) { is PackageFragmentDescriptor -> { - fun getPackage(decl: PackageFragmentDescriptor) = decl.containingDeclaration.getPackage(decl.fqName) + + fun getPackage(declaration: PackageFragmentDescriptor) = + declaration.containingDeclaration.getPackage(declaration.fqName) + val packageDescriptor = getPackage(currentScopeDeclaration) if ((declaration.containingDeclaration)?.fqNameOrNull() == currentScopeDeclaration.fqNameOrNull()) { return @@ -592,7 +596,7 @@ class MoveConflictChecker( .memberScope .getContributedDescriptors { it == declaration.name } .filter { equivalent(it, declaration) } - .forEach { report(descrText(it), packageDescriptor.fqName.asString()) } + .forEach { report(it, packageDescriptor) } return } is ClassDescriptor -> { @@ -601,7 +605,7 @@ class MoveConflictChecker( .unsubstitutedMemberScope .getContributedDescriptors { it == declaration.name } .filter { equivalent(it, declaration) } - .forEach { report(descrText(it), descrText(currentScopeDeclaration)) } + .forEach { report(it, currentScopeDeclaration) } } } @@ -615,15 +619,15 @@ class MoveConflictChecker( val declarationDescriptor = (declaration as KtElement).analyze().get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration) if (declarationDescriptor is DeclarationDescriptor) { - val baseDescriptor = moveTarget.getContainerDescriptor() - if (baseDescriptor != null) { - walkDeclarations(baseDescriptor, declarationDescriptor) { conflictingDecl, scopeName -> - conflicts.putValue( - declaration, - "Following declarations would clash: \"${declaration.getText()}\" (element to move) " + - "and \"\n$conflictingDecl\" declared in scope " + - "$scopeName (move destination)" - ) + + moveTarget.getContainerDescriptor()?.let { baseDescriptor -> + walkDeclarations(baseDescriptor, declarationDescriptor) { conflictingDeclaration, conflictingScope -> + val message = + "Following declarations would clash: to move ${render(declarationDescriptor)} " + + "and destination ${render(conflictingDeclaration)} declared in scope " + + render(conflictingScope) + + conflicts.putValue(declaration, message) } } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/pullUpConflictsUtils.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/pullUpConflictsUtils.kt index 0bbea8bd657..af6bdac5fc6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/pullUpConflictsUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/pullUp/pullUpConflictsUtils.kt @@ -49,12 +49,14 @@ import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.substitutions.getTypeSubstitutor import org.jetbrains.kotlin.util.findCallableMemberBySignature -fun checkConflicts(project: Project, - sourceClass: KtClassOrObject, - targetClass: PsiNamedElement, - memberInfos: List, - onShowConflicts: () -> Unit = {}, - onAccept: () -> Unit) { +fun checkConflicts( + project: Project, + sourceClass: KtClassOrObject, + targetClass: PsiNamedElement, + memberInfos: List, + onShowConflicts: () -> Unit = {}, + onAccept: () -> Unit +) { val conflicts = MultiMap() val pullUpData = KotlinPullUpData(sourceClass, @@ -127,9 +129,12 @@ private val CALLABLE_RENDERER = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_N fun DeclarationDescriptor.renderForConflicts(): String { return when (this) { - is ClassDescriptor -> "${DescriptorRenderer.getClassifierKindPrefix(this)} ${IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(this)}" + is ClassDescriptor -> "${DescriptorRenderer.getClassifierKindPrefix(this)} " + + IdeDescriptorRenderers.SOURCE_CODE.renderClassifierName(this) is FunctionDescriptor -> "function '${CALLABLE_RENDERER.render(this)}'" is PropertyDescriptor -> "property '${CALLABLE_RENDERER.render(this)}'" + is PackageFragmentDescriptor -> fqName.asString() + is PackageViewDescriptor -> fqName.asString() else -> "" } } @@ -140,9 +145,9 @@ internal fun KotlinPullUpData.getClashingMemberInTargetClass(memberDescriptor: C } private fun KotlinPullUpData.checkClashWithSuperDeclaration( - member: KtNamedDeclaration, - memberDescriptor: DeclarationDescriptor, - conflicts: MultiMap + member: KtNamedDeclaration, + memberDescriptor: DeclarationDescriptor, + conflicts: MultiMap ) { val message = "${targetClassDescriptor.renderForConflicts()} already contains ${memberDescriptor.renderForConflicts()}" @@ -169,40 +174,44 @@ private fun PsiClass.isSourceOrTarget(data: KotlinPullUpData): Boolean { } private fun KotlinPullUpData.checkAccidentalOverrides( - member: KtNamedDeclaration, - memberDescriptor: DeclarationDescriptor, - conflicts: MultiMap) { + member: KtNamedDeclaration, + memberDescriptor: DeclarationDescriptor, + conflicts: MultiMap +) { if (memberDescriptor is CallableDescriptor && !member.hasModifier(KtTokens.PRIVATE_KEYWORD)) { val memberDescriptorInTargetClass = memberDescriptor.substitute(sourceToTargetClassSubstitutor) if (memberDescriptorInTargetClass != null) { HierarchySearchRequest(targetClass, targetClass.useScope) - .searchInheritors() - .asSequence() - .filterNot { it.isSourceOrTarget(this) } - .mapNotNull { it.unwrapped as? KtClassOrObject } - .forEach { - val subClassDescriptor = it.resolveToDescriptorWrapperAware(resolutionFacade) as ClassDescriptor - val substitutor = getTypeSubstitutor(targetClassDescriptor.defaultType, - subClassDescriptor.defaultType) ?: TypeSubstitutor.EMPTY - val memberDescriptorInSubClass = - memberDescriptorInTargetClass.substitute(substitutor) as? CallableMemberDescriptor - val clashingMemberDescriptor = - memberDescriptorInSubClass?.let { subClassDescriptor.findCallableMemberBySignature(it) } ?: return - val clashingMember = clashingMemberDescriptor.source.getPsi() ?: return + .searchInheritors() + .asSequence() + .filterNot { it.isSourceOrTarget(this) } + .mapNotNull { it.unwrapped as? KtClassOrObject } + .forEach { + val subClassDescriptor = it.resolveToDescriptorWrapperAware(resolutionFacade) as ClassDescriptor + val substitutor = getTypeSubstitutor( + targetClassDescriptor.defaultType, + subClassDescriptor.defaultType + ) ?: TypeSubstitutor.EMPTY + val memberDescriptorInSubClass = + memberDescriptorInTargetClass.substitute(substitutor) as? CallableMemberDescriptor + val clashingMemberDescriptor = + memberDescriptorInSubClass?.let { subClassDescriptor.findCallableMemberBySignature(it) } ?: return + val clashingMember = clashingMemberDescriptor.source.getPsi() ?: return - val message = memberDescriptor.renderForConflicts() + - " in super class would clash with existing member of " + - it.resolveToDescriptorWrapperAware(resolutionFacade).renderForConflicts() - conflicts.putValue(clashingMember, message.capitalize()) - } + val message = memberDescriptor.renderForConflicts() + + " in super class would clash with existing member of " + + it.resolveToDescriptorWrapperAware(resolutionFacade).renderForConflicts() + conflicts.putValue(clashingMember, message.capitalize()) + } } } } private fun KotlinPullUpData.checkInnerClassToInterface( - member: KtNamedDeclaration, - memberDescriptor: DeclarationDescriptor, - conflicts: MultiMap) { + member: KtNamedDeclaration, + memberDescriptor: DeclarationDescriptor, + conflicts: MultiMap +) { if (isInterfaceTarget && memberDescriptor is ClassDescriptor && memberDescriptor.isInner) { val message = "${memberDescriptor.renderForConflicts()} is an inner class. It can not be moved to the interface" conflicts.putValue(member, message.capitalize()) @@ -210,19 +219,20 @@ private fun KotlinPullUpData.checkInnerClassToInterface( } private fun KotlinPullUpData.checkVisibility( - memberInfo: KotlinMemberInfo, - memberDescriptor: DeclarationDescriptor, - conflicts: MultiMap + memberInfo: KotlinMemberInfo, + memberDescriptor: DeclarationDescriptor, + conflicts: MultiMap ) { fun reportConflictIfAny(targetDescriptor: DeclarationDescriptor) { if (targetDescriptor in memberDescriptors.values) return val target = (targetDescriptor as? DeclarationDescriptorWithSource)?.source?.getPsi() ?: return if (targetDescriptor is DeclarationDescriptorWithVisibility - && !Visibilities.isVisibleIgnoringReceiver(targetDescriptor, targetClassDescriptor)) { + && !Visibilities.isVisibleIgnoringReceiver(targetDescriptor, targetClassDescriptor) + ) { val message = RefactoringBundle.message( - "0.uses.1.which.is.not.accessible.from.the.superclass", - memberDescriptor.renderForConflicts(), - targetDescriptor.renderForConflicts() + "0.uses.1.which.is.not.accessible.from.the.superclass", + memberDescriptor.renderForConflicts(), + targetDescriptor.renderForConflicts() ) conflicts.putValue(target, message.capitalize()) } @@ -242,19 +252,19 @@ private fun KotlinPullUpData.checkVisibility( } } - childrenToCheck.forEach { - it.accept( - object : KtTreeVisitorVoid() { - override fun visitReferenceExpression(expression: KtReferenceExpression) { - super.visitReferenceExpression(expression) + childrenToCheck.forEach { children -> + children.accept( + object : KtTreeVisitorVoid() { + override fun visitReferenceExpression(expression: KtReferenceExpression) { + super.visitReferenceExpression(expression) - val context = resolutionFacade.analyze(expression) - expression.references - .flatMap { (it as? KtReference)?.resolveToDescriptors(context) ?: emptyList() } - .forEach(::reportConflictIfAny) + val context = resolutionFacade.analyze(expression) + expression.references + .flatMap { (it as? KtReference)?.resolveToDescriptors(context) ?: emptyList() } + .forEach(::reportConflictIfAny) - } } + } ) } } \ No newline at end of file