Cleanup: KotlinSafeDeleteProcessor

This commit is contained in:
Mikhail Glukhikh
2018-06-26 13:11:59 +03:00
parent 8848d7a043
commit 5bdaef4983
@@ -51,7 +51,6 @@ import org.jetbrains.kotlin.idea.refactoring.isTrueJavaMethod
import org.jetbrains.kotlin.idea.references.KtReference import org.jetbrains.kotlin.idea.references.KtReference
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters
import org.jetbrains.kotlin.idea.search.usagesSearch.constructor
import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstructorUsages import org.jetbrains.kotlin.idea.search.usagesSearch.processDelegationCallConstructorUsages
import org.jetbrains.kotlin.idea.util.actualsForExpected import org.jetbrains.kotlin.idea.util.actualsForExpected
import org.jetbrains.kotlin.idea.util.liftToExpected import org.jetbrains.kotlin.idea.util.liftToExpected
@@ -78,7 +77,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
override fun handlesElement(element: PsiElement): Boolean = element.canDeleteElement() override fun handlesElement(element: PsiElement): Boolean = element.canDeleteElement()
override fun findUsages( override fun findUsages(
element: PsiElement, allElementsToDelete: Array<out PsiElement>, usages: MutableList<UsageInfo> element: PsiElement, allElementsToDelete: Array<out PsiElement>, usages: MutableList<UsageInfo>
): NonCodeUsageSearchInfo { ): NonCodeUsageSearchInfo {
val deleteSet = SmartSet.create<PsiElement>() val deleteSet = SmartSet.create<PsiElement>()
deleteSet.addAll(allElementsToDelete) deleteSet.addAll(allElementsToDelete)
@@ -91,16 +90,18 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
fun getSearchInfo(element: PsiElement) = NonCodeUsageSearchInfo(getIgnoranceCondition(), element) fun getSearchInfo(element: PsiElement) = NonCodeUsageSearchInfo(getIgnoranceCondition(), element)
fun searchKotlinDeclarationReferences(declaration: KtDeclaration): Sequence<PsiReference> { fun searchKotlinDeclarationReferences(declaration: KtDeclaration): Sequence<PsiReference> {
val elementsToSearch = if (declaration is KtParameter) declaration.withExpectedActuals() else listOf(declaration) val elementsToSearch = when (declaration) {
is KtParameter -> declaration.withExpectedActuals()
else -> listOf(declaration)
}
return elementsToSearch.asSequence().flatMap { return elementsToSearch.asSequence().flatMap {
val searchParameters = KotlinReferencesSearchParameters( val searchParameters = KotlinReferencesSearchParameters(
it, it,
it.useScope, it.useScope,
kotlinOptions = KotlinReferencesSearchOptions(acceptCallableOverrides = true) kotlinOptions = KotlinReferencesSearchOptions(acceptCallableOverrides = true)
) )
ReferencesSearch.search(searchParameters) ReferencesSearch.search(searchParameters).asSequence()
.asSequence() .filterNot { reference -> getIgnoranceCondition().value(reference.element) }
.filterNot { reference -> getIgnoranceCondition().value(reference.element) }
} }
} }
@@ -135,7 +136,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
} }
fun asLightElements(ktElements: Array<out PsiElement>) = fun asLightElements(ktElements: Array<out PsiElement>) =
ktElements.flatMap { (it as? KtElement)?.toLightElements() ?: listOf(it) }.toTypedArray() ktElements.flatMap { (it as? KtElement)?.toLightElements() ?: listOf(it) }.toTypedArray()
fun findUsagesByJavaProcessor(element: PsiElement, forceReferencedElementUnwrapping: Boolean): NonCodeUsageSearchInfo? { fun findUsagesByJavaProcessor(element: PsiElement, forceReferencedElementUnwrapping: Boolean): NonCodeUsageSearchInfo? {
val javaUsages = ArrayList<UsageInfo>() val javaUsages = ArrayList<UsageInfo>()
@@ -143,7 +144,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
val elementToPassToJava = when (element) { val elementToPassToJava = when (element) {
is KtLightFieldImpl<*> -> object : KtLightField by element { is KtLightFieldImpl<*> -> object : KtLightField by element {
// Suppress walking through initializer compiled PSI (it doesn't contain any reference expressions anyway) // Suppress walking through initializer compiled PSI (it doesn't contain any reference expressions anyway)
override fun getInitializer() = null override fun getInitializer(): PsiExpression? = null
} }
else -> element else -> element
} }
@@ -180,7 +181,11 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
usageElement.getNonStrictParentOfType<KtImportDirective>()?.let { importDirective -> usageElement.getNonStrictParentOfType<KtImportDirective>()?.let { importDirective ->
SafeDeleteImportDirectiveUsageInfo(importDirective, element) SafeDeleteImportDirectiveUsageInfo(importDirective, element)
} ?: usageElement.getParentOfTypeAndBranch<KtSuperTypeEntry> { typeReference }?.let { } ?: usageElement.getParentOfTypeAndBranch<KtSuperTypeEntry> { typeReference }?.let {
if (element is PsiClass && element.isInterface) SafeDeleteSuperTypeUsageInfo(it, element) else usageInfo if (element is PsiClass && element.isInterface) {
SafeDeleteSuperTypeUsageInfo(it, element)
} else {
usageInfo
}
} ?: if (forceReferencedElementUnwrapping) { } ?: if (forceReferencedElementUnwrapping) {
SafeDeleteReferenceJavaDeleteUsageInfo(usageElement, element.unwrapped, usageInfo.isSafeDelete) SafeDeleteReferenceJavaDeleteUsageInfo(usageElement, element.unwrapped, usageInfo.isSafeDelete)
} else usageInfo } else usageInfo
@@ -196,9 +201,8 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
} }
fun findUsagesByJavaProcessor(elements: Sequence<PsiElement>, insideDeleted: Condition<PsiElement>): Condition<PsiElement> = fun findUsagesByJavaProcessor(elements: Sequence<PsiElement>, insideDeleted: Condition<PsiElement>): Condition<PsiElement> =
elements elements.mapNotNull { element -> findUsagesByJavaProcessor(element, true)?.insideDeletedCondition }
.mapNotNull { element -> findUsagesByJavaProcessor(element, true)?.insideDeletedCondition } .fold(insideDeleted) { condition1, condition2 -> Conditions.or(condition1, condition2) }
.fold(insideDeleted) { condition1, condition2 -> Conditions.or(condition1, condition2) }
fun findUsagesByJavaProcessor(ktDeclaration: KtDeclaration): NonCodeUsageSearchInfo { fun findUsagesByJavaProcessor(ktDeclaration: KtDeclaration): NonCodeUsageSearchInfo {
val lightElements = ktDeclaration.toLightElements() val lightElements = ktDeclaration.toLightElements()
@@ -206,11 +210,11 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
return findKotlinDeclarationUsages(ktDeclaration) return findKotlinDeclarationUsages(ktDeclaration)
} }
return NonCodeUsageSearchInfo( return NonCodeUsageSearchInfo(
findUsagesByJavaProcessor( findUsagesByJavaProcessor(
lightElements.asSequence(), lightElements.asSequence(),
getIgnoranceCondition() getIgnoranceCondition()
), ),
ktDeclaration ktDeclaration
) )
} }
@@ -226,7 +230,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
val referencedElement = reference.element val referencedElement = reference.element
val argList = referencedElement.getNonStrictParentOfType<KtUserType>()?.typeArgumentList val argList = referencedElement.getNonStrictParentOfType<KtUserType>()?.typeArgumentList
?: referencedElement.getNonStrictParentOfType<KtCallExpression>()?.typeArgumentList ?: referencedElement.getNonStrictParentOfType<KtCallExpression>()?.typeArgumentList
if (argList != null) { if (argList != null) {
val projections = argList.arguments val projections = argList.arguments
@@ -270,13 +274,11 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
is KtNamedFunction -> { is KtNamedFunction -> {
if (element.isLocal) { if (element.isLocal) {
findKotlinDeclarationUsages(element) findKotlinDeclarationUsages(element)
} } else {
else {
val lightMethods = element.toLightMethods() val lightMethods = element.toLightMethods()
if (lightMethods.isNotEmpty()) { if (lightMethods.isNotEmpty()) {
lightMethods.map { method -> findUsagesByJavaProcessor(method, false) }.firstOrNull() lightMethods.map { method -> findUsagesByJavaProcessor(method, false) }.firstOrNull()
} } else {
else {
findKotlinDeclarationUsages(element) findKotlinDeclarationUsages(element)
} }
} }
@@ -293,8 +295,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
is KtProperty -> { is KtProperty -> {
if (element.isLocal) { if (element.isLocal) {
findKotlinDeclarationUsages(element) findKotlinDeclarationUsages(element)
} } else {
else {
findUsagesByJavaProcessor(element) findUsagesByJavaProcessor(element)
} }
} }
@@ -326,20 +327,20 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
val bindingContext = (element as KtElement).analyze() val bindingContext = (element as KtElement).analyze()
val declarationDescriptor = val declarationDescriptor =
bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? CallableMemberDescriptor ?: return null bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? CallableMemberDescriptor ?: return null
return declarationDescriptor.overriddenDescriptors return declarationDescriptor.overriddenDescriptors
.asSequence() .asSequence()
.filter { overridenDescriptor -> overridenDescriptor.modality == Modality.ABSTRACT } .filter { overridenDescriptor -> overridenDescriptor.modality == Modality.ABSTRACT }
.mapTo(ArrayList()) { overridenDescriptor -> .mapTo(ArrayList()) { overridenDescriptor ->
KotlinBundle.message( KotlinBundle.message(
"x.implements.y", "x.implements.y",
formatFunction(declarationDescriptor, true), formatFunction(declarationDescriptor, true),
formatClass(declarationDescriptor.containingDeclaration, true), formatClass(declarationDescriptor.containingDeclaration, true),
formatFunction(overridenDescriptor, true), formatFunction(overridenDescriptor, true),
formatClass(overridenDescriptor.containingDeclaration, true) formatClass(overridenDescriptor.containingDeclaration, true)
) )
} }
} }
return super.findConflicts(element, allElementsToDelete) return super.findConflicts(element, allElementsToDelete)
@@ -383,8 +384,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
element.actualsForExpected().forEach { element.actualsForExpected().forEach {
if (it is KtParameter) { if (it is KtParameter) {
(it.parent as? KtParameterList)?.removeParameter(it) (it.parent as? KtParameterList)?.removeParameter(it)
} } else {
else {
it.removeModifier(KtTokens.IMPL_KEYWORD) it.removeModifier(KtTokens.IMPL_KEYWORD)
it.removeModifier(KtTokens.ACTUAL_KEYWORD) it.removeModifier(KtTokens.ACTUAL_KEYWORD)
} }
@@ -424,24 +424,24 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
if (ApplicationManager.getApplication().isUnitTestMode) return parameter.project.ALLOW_LIFTING_ACTUAL_PARAMETER_TO_EXPECTED if (ApplicationManager.getApplication().isUnitTestMode) return parameter.project.ALLOW_LIFTING_ACTUAL_PARAMETER_TO_EXPECTED
return Messages.showYesNoDialog( return Messages.showYesNoDialog(
"Do you want to delete this parameter in expected declaration and all related actual ones?", "Do you want to delete this parameter in expected declaration and all related actual ones?",
RefactoringBundle.message("safe.delete.title"), RefactoringBundle.message("safe.delete.title"),
Messages.getQuestionIcon() Messages.getQuestionIcon()
) == Messages.YES ) == Messages.YES
} }
override fun getElementsToSearch( override fun getElementsToSearch(
element: PsiElement, module: Module?, allElementsToDelete: Collection<PsiElement> element: PsiElement, module: Module?, allElementsToDelete: Collection<PsiElement>
): Collection<PsiElement>? { ): Collection<PsiElement>? {
when (element) { when (element) {
is KtParameter -> { is KtParameter -> {
val expectParameter = element.liftToExpected() as? KtParameter val expectParameter = element.liftToExpected() as? KtParameter
if (expectParameter != null && expectParameter != element) { if (expectParameter != null && expectParameter != element) {
if (shouldAllowPropagationToExpected(element)) { return if (shouldAllowPropagationToExpected(element)) {
return listOf(expectParameter) listOf(expectParameter)
} else { } else {
element.ownerFunction?.dropActualModifier = true element.ownerFunction?.dropActualModifier = true
return listOf(element) listOf(element)
} }
} }
@@ -457,8 +457,10 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
if (ApplicationManager.getApplication()!!.isUnitTestMode) return Collections.singletonList(element) if (ApplicationManager.getApplication()!!.isUnitTestMode) return Collections.singletonList(element)
return when (element) { return when (element) {
is KtNamedFunction, is KtProperty -> checkSuperMethods(element as KtDeclaration, allElementsToDelete, "delete (with usage search)") is KtNamedFunction, is KtProperty ->
else -> super.getElementsToSearch(element, module, allElementsToDelete) checkSuperMethods(element as KtDeclaration, allElementsToDelete, "delete (with usage search)")
else ->
super.getElementsToSearch(element, module, allElementsToDelete)
} }
} }
} }