From 2260f66e0264d620b35e1e0d50481c30e7ffd169 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 12 Apr 2018 14:29:08 +0300 Subject: [PATCH] Unify usage of ProgressManager.progressIndicator --- .idea/inspectionProfiles/idea_default.xml | 1 + .../kotlin/idea/util/ApplicationUtils.kt | 11 +- .../SearchNotPropertyCandidatesAction.kt | 3 +- .../SearchNotPropertyCandidatesAction.kt.181 | 164 -------- ...unctionTypeParameterToReceiverIntention.kt | 3 +- ...ionTypeParameterToReceiverIntention.kt.181 | 356 ------------------ ...unctionTypeReceiverToParameterIntention.kt | 3 +- ...ionTypeReceiverToParameterIntention.kt.181 | 222 ----------- .../ConvertPropertyToFunctionIntention.kt | 3 +- .../ConvertPropertyToFunctionIntention.kt.181 | 201 ---------- 10 files changed, 19 insertions(+), 948 deletions(-) delete mode 100644 idea/src/org/jetbrains/kotlin/idea/actions/internal/SearchNotPropertyCandidatesAction.kt.181 delete mode 100644 idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeParameterToReceiverIntention.kt.181 delete mode 100644 idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt.181 delete mode 100644 idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyToFunctionIntention.kt.181 diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml index 5486cf6edd6..4f20b3cd9ec 100644 --- a/.idea/inspectionProfiles/idea_default.xml +++ b/.idea/inspectionProfiles/idea_default.xml @@ -280,6 +280,7 @@ + diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt index a6937ee8d42..2c54a6e904d 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/util/ApplicationUtils.kt @@ -18,6 +18,9 @@ package org.jetbrains.kotlin.idea.util.application import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.command.CommandProcessor +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.ProgressIndicatorProvider +import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project fun runReadAction(action: () -> T): T { @@ -41,4 +44,10 @@ fun Project.executeCommand(name: String, groupId: Any? = null, command: () - CommandProcessor.getInstance().executeCommand(this, { result = command() }, name, groupId) @Suppress("USELESS_CAST") return result as T -} \ No newline at end of file +} + +/** + * ProgressManager.getProgressIndicator() is nullable in 181 and dynamic again in 182 + * BUNCH: 181 + */ +val ProgressManager.progressIndicatorNullable: ProgressIndicator? get() = progressIndicator \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/internal/SearchNotPropertyCandidatesAction.kt b/idea/src/org/jetbrains/kotlin/idea/actions/internal/SearchNotPropertyCandidatesAction.kt index 6fb3e2426a0..c9c99eddf9b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/actions/internal/SearchNotPropertyCandidatesAction.kt +++ b/idea/src/org/jetbrains/kotlin/idea/actions/internal/SearchNotPropertyCandidatesAction.kt @@ -29,6 +29,7 @@ import com.intellij.psi.PsiModifier import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde +import org.jetbrains.kotlin.idea.util.application.progressIndicatorNullable import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.load.java.isFromJava import org.jetbrains.kotlin.name.FqName @@ -54,7 +55,7 @@ class SearchNotPropertyCandidatesAction : AnAction() { ProgressManager.getInstance().runProcessWithProgressSynchronously( { runReadAction { - ProgressManager.getInstance().progressIndicator.isIndeterminate = true + ProgressManager.getInstance().progressIndicatorNullable!!.isIndeterminate = true processAllDescriptors(packageDesc, project) } }, diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/internal/SearchNotPropertyCandidatesAction.kt.181 b/idea/src/org/jetbrains/kotlin/idea/actions/internal/SearchNotPropertyCandidatesAction.kt.181 deleted file mode 100644 index 998844a3b11..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/actions/internal/SearchNotPropertyCandidatesAction.kt.181 +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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.actions.internal - - -import com.intellij.openapi.actionSystem.AnAction -import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.actionSystem.CommonDataKeys -import com.intellij.openapi.progress.ProgressManager -import com.intellij.openapi.progress.ProgressManager.progress -import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.Messages -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiModifier -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor -import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde -import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.load.java.isFromJava -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe - - -class SearchNotPropertyCandidatesAction : AnAction() { - override fun actionPerformed(e: AnActionEvent?) { - val project = e?.project!! - val psiFile = e.getData(CommonDataKeys.PSI_FILE) as? KtFile ?: return - - val desc = psiFile.findModuleDescriptor() - val result = Messages.showInputDialog("Enter package FqName", "Search for Not Property candidates", Messages.getQuestionIcon()) - val packageDesc = try { - val fqName = FqName.fromSegments(result!!.split('.')) - desc.getPackage(fqName) - } - catch (e: Exception) { - return - } - - ProgressManager.getInstance().runProcessWithProgressSynchronously( - { - runReadAction { - ProgressManager.getInstance().progressIndicator!!.isIndeterminate = true - processAllDescriptors(packageDesc, project) - } - }, - "Searching for Not Property candidates", - true, - project) - } - - - private fun processAllDescriptors(desc: DeclarationDescriptor, project: Project) { - val processed = mutableSetOf() - var pFunctions = 0 - val matchedDescriptors = mutableSetOf() - - fun recursive(desc: DeclarationDescriptor) { - if (desc in processed) return - progress("Step 1: Collecting ${processed.size}:$pFunctions:${matchedDescriptors.size}", "$desc") - when (desc) { - - is ModuleDescriptor -> recursive(desc.getPackage(FqName("java"))) - is ClassDescriptor -> desc.unsubstitutedMemberScope.getContributedDescriptors { true }.forEach(::recursive) - is PackageViewDescriptor -> desc.memberScope.getContributedDescriptors { true }.forEach(::recursive) - - is FunctionDescriptor -> { - if (desc.isFromJava) { - val name = desc.fqNameUnsafe.shortName().asString() - if (name.length > 3 && - ((name.startsWith("get") && desc.valueParameters.isEmpty() && desc.returnType != null) || - (name.startsWith("set") && desc.valueParameters.size == 1))) { - if (desc in matchedDescriptors) return - matchedDescriptors += desc - } - } - pFunctions++ - return - } - - } - processed += desc - } - recursive(desc) - val resultDescriptors = mutableSetOf() - matchedDescriptors.flatMapTo(resultDescriptors) { - sequenceOf(it, *(it.overriddenDescriptors.toTypedArray())).asIterable() - } - println("Found ${resultDescriptors.size} accessors") - - - fun PsiMethod.isTrivial(): Boolean { - val t = this.text - val s = t.indexOf('{') - val e = t.lastIndexOf('}') - return if (s != e && s != -1) t.substring(s, e).lines().size <= 3 else true - } - - - val descriptorToPsiBinding = mutableMapOf() - - - var i = 0 - resultDescriptors.forEach { desc -> - progress("Step 2: ${i++} of ${resultDescriptors.size}", "$desc") - val source = DescriptorToSourceUtilsIde.getAllDeclarations(project, desc) - .filterIsInstance() - .firstOrNull() ?: return@forEach - val abstract = source.modifierList.hasModifierProperty(PsiModifier.ABSTRACT) - if (!abstract) { - if (!source.isTrivial()) { - descriptorToPsiBinding[desc] = source - } - } - } - - val nonTrivial = mutableSetOf() - i = 0 - descriptorToPsiBinding.forEach { t, u -> - progress("Step 3: ${i++} of ${descriptorToPsiBinding.size}", "$t") - val descriptors = t.overriddenDescriptors - var impl = false - descriptors.forEach { - val source = DescriptorToSourceUtilsIde.getAllDeclarations(project, it).filterIsInstance().firstOrNull() - if (source != null) { - if (source.body != null || source.hasModifierProperty(PsiModifier.ABSTRACT)) - nonTrivial += it - impl = true - } - } - if (u.body != null) - if (!impl) - nonTrivial += t - } - nonTrivial.forEach(::println) - println("Non trivial count: ${nonTrivial.size}") - } - - override fun update(e: AnActionEvent) { - if (!KotlinInternalMode.enabled) { - e.presentation.isVisible = false - e.presentation.isEnabled = false - } - else { - e.presentation.isVisible = true - e.presentation.isEnabled = e.getData(CommonDataKeys.PSI_FILE) is KtFile - } - } - -} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeParameterToReceiverIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeParameterToReceiverIntention.kt index 7de2e4b5a77..67b6091ffe9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeParameterToReceiverIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeParameterToReceiverIntention.kt @@ -41,6 +41,7 @@ import org.jetbrains.kotlin.idea.references.KtSimpleReference import org.jetbrains.kotlin.idea.runSynchronouslyWithProgress import org.jetbrains.kotlin.idea.search.usagesSearch.searchReferencesOrMethodReferences import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.idea.util.application.progressIndicatorNullable import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType @@ -186,7 +187,7 @@ class ConvertFunctionTypeParameterToReceiverIntention : SelfTargetingRangeIntent runReadAction { val progressStep = 1.0/callables.size for ((i, callable) in callables.withIndex()) { - ProgressManager.getInstance().progressIndicator.fraction = (i + 1) * progressStep + ProgressManager.getInstance().progressIndicatorNullable!!.fraction = (i + 1) * progressStep if (callable !is PsiNamedElement) continue diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeParameterToReceiverIntention.kt.181 b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeParameterToReceiverIntention.kt.181 deleted file mode 100644 index b1f10a8a30c..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeParameterToReceiverIntention.kt.181 +++ /dev/null @@ -1,356 +0,0 @@ -/* - * 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.intentions - -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.progress.ProgressManager -import com.intellij.openapi.util.TextRange -import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiNamedElement -import com.intellij.psi.search.LocalSearchScope -import com.intellij.psi.search.searches.ReferencesSearch -import com.intellij.refactoring.util.RefactoringUIUtil -import com.intellij.util.containers.MultiMap -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor -import org.jetbrains.kotlin.idea.core.* -import org.jetbrains.kotlin.idea.refactoring.CallableRefactoring -import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.explicateReceiverOf -import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively -import org.jetbrains.kotlin.idea.refactoring.getAffectedCallables -import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler -import org.jetbrains.kotlin.idea.references.KtReference -import org.jetbrains.kotlin.idea.references.KtSimpleReference -import org.jetbrains.kotlin.idea.runSynchronouslyWithProgress -import org.jetbrains.kotlin.idea.search.usagesSearch.searchReferencesOrMethodReferences -import org.jetbrains.kotlin.idea.util.application.executeWriteCommand -import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType -import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject -import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType -import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch -import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.bindingContextUtil.getAbbreviatedTypeOrType -import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getArgumentByParameterIndex -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.types.KotlinType - -class ConvertFunctionTypeParameterToReceiverIntention : SelfTargetingRangeIntention( - KtTypeReference::class.java, - "Convert function type parameter to receiver" -) { - class FunctionDefinitionInfo(element: KtFunction) : AbstractProcessableUsageInfo(element) { - override fun process(data: ConversionData, elementsToShorten: MutableList) { - val function = element ?: return - val functionParameter = function.valueParameters.getOrNull(data.functionParameterIndex) ?: return - val functionType = functionParameter.typeReference?.typeElement as? KtFunctionType ?: return - val functionTypeParameterList = functionType.parameterList ?: return - val parameterToMove = functionTypeParameterList.parameters.getOrNull(data.typeParameterIndex) ?: return - val typeReferenceToMove = parameterToMove.typeReference ?: return - functionType.setReceiverTypeReference(typeReferenceToMove) - functionTypeParameterList.removeParameter(parameterToMove) - } - } - - class ParameterCallInfo(element: KtCallExpression) : AbstractProcessableUsageInfo(element) { - override fun process(data: ConversionData, elementsToShorten: MutableList) { - val callExpression = element ?: return - val argumentList = callExpression.valueArgumentList ?: return - val expressionToMove = argumentList.arguments.getOrNull(data.typeParameterIndex)?.getArgumentExpression() ?: return - val callWithReceiver = KtPsiFactory(callExpression).createExpressionByPattern("$0.$1", expressionToMove, callExpression) as KtQualifiedExpression - (callWithReceiver.selectorExpression as KtCallExpression).valueArgumentList!!.removeArgument(data.typeParameterIndex) - callExpression.replace(callWithReceiver) - } - } - - class InternalReferencePassInfo(element: KtSimpleNameExpression) : AbstractProcessableUsageInfo(element) { - override fun process(data: ConversionData, elementsToShorten: MutableList) { - val expression = element ?: return - val lambdaType = data.lambdaType - val validator = CollectingNameValidator() - val parameterNames = lambdaType.arguments - .dropLast(1) - .map { KotlinNameSuggester.suggestNamesByType(it.type, validator, "p").first() } - val receiver = parameterNames.getOrNull(data.typeParameterIndex) ?: return - val arguments = parameterNames.filter { it != receiver } - val adapterLambda = KtPsiFactory(expression).createLambdaExpression( - parameterNames.joinToString(), - "$receiver.${expression.text}(${arguments.joinToString()})" - ) - expression.replaced(adapterLambda).let { - MoveLambdaOutsideParenthesesIntention.moveFunctionLiteralOutsideParenthesesIfPossible(it) - } - } - } - - class LambdaInfo(element: KtExpression) : AbstractProcessableUsageInfo(element) { - override fun process(data: ConversionData, elementsToShorten: MutableList) { - val expression = element ?: return - val context = expression.analyze(BodyResolveMode.PARTIAL) - val psiFactory = KtPsiFactory(expression) - - if (expression is KtLambdaExpression || (expression !is KtSimpleNameExpression && expression !is KtCallableReferenceExpression)) { - expression.forEachDescendantOfType { - if (it.getLabelName() != null) return@forEachDescendantOfType - val descriptor = context[BindingContext.REFERENCE_TARGET, it.instanceReference] ?: return@forEachDescendantOfType - it.replace(psiFactory.createExpression(explicateReceiverOf(descriptor))) - } - } - - if (expression is KtLambdaExpression) { - expression.valueParameters.getOrNull(data.typeParameterIndex)?.let { parameterToConvert -> - val thisRefExpr = psiFactory.createThisExpression() - for (ref in ReferencesSearch.search(parameterToConvert, LocalSearchScope(expression))) { - (ref.element as? KtSimpleNameExpression)?.replace(thisRefExpr) - } - val lambda = expression.functionLiteral - lambda.valueParameterList!!.removeParameter(parameterToConvert) - if (lambda.valueParameters.isEmpty()) { - lambda.arrow?.delete() - } - } - return - } - - val originalLambdaTypes = data.lambdaType - val originalParameterTypes = originalLambdaTypes.arguments.dropLast(1).map { it.type } - - val calleeText = when (expression) { - is KtSimpleNameExpression -> expression.text - is KtCallableReferenceExpression -> "(${expression.text})" - else -> generateVariable(expression) - } - - val parameterNameValidator = CollectingNameValidator( - if (expression !is KtCallableReferenceExpression) listOf(calleeText) else emptyList() - ) - val parameterNamesWithReceiver = originalParameterTypes.mapIndexed { i, type -> - if (i != data.typeParameterIndex) KotlinNameSuggester.suggestNamesByType(type, parameterNameValidator, "p").first() else "this" - } - val parameterNames = parameterNamesWithReceiver.filter { it != "this" } - - val body = psiFactory.createExpression(parameterNamesWithReceiver.joinToString(prefix = "$calleeText(", postfix = ")")) - - val replacingLambda = psiFactory.buildExpression { - appendFixedText("{ ") - appendFixedText(parameterNames.joinToString()) - appendFixedText(" -> ") - appendExpression(body) - appendFixedText(" }") - } as KtLambdaExpression - - expression.replaced(replacingLambda).let { - MoveLambdaOutsideParenthesesIntention.moveFunctionLiteralOutsideParenthesesIfPossible(it) - } - } - - private fun generateVariable(expression: KtExpression): String { - var baseCallee = "" - KotlinIntroduceVariableHandler.doRefactoring(project, null, expression, false, emptyList()) { - baseCallee = it.name!! - } - return baseCallee - } - } - - private inner class Converter( - private val data: ConversionData - ) : CallableRefactoring(data.function.project, data.functionDescriptor, text) { - override fun performRefactoring(descriptorsForChange: Collection) { - val callables = getAffectedCallables(project, descriptorsForChange) - - val conflicts = MultiMap() - - val usages = ArrayList>() - - project.runSynchronouslyWithProgress("Looking for usages and conflicts...", true) { - runReadAction { - val progressStep = 1.0/callables.size - for ((i, callable) in callables.withIndex()) { - ProgressManager.getInstance().progressIndicator!!.fraction = (i + 1) * progressStep - - if (callable !is PsiNamedElement) continue - - if (!checkModifiable(callable)) { - val renderedCallable = RefactoringUIUtil.getDescription(callable, true).capitalize() - conflicts.putValue(callable, "Can't modify $renderedCallable") - } - - usageLoop@ for (ref in callable.searchReferencesOrMethodReferences()) { - val refElement = ref.element ?: continue - when (ref) { - is KtSimpleReference<*> -> processExternalUsage(conflicts, refElement, usages) - is KtReference -> continue@usageLoop - else -> { - if (data.isFirstParameter) continue@usageLoop - conflicts.putValue( - refElement, - "Can't replace non-Kotlin reference with call expression: " + StringUtil.htmlEmphasize(refElement.text) - ) - } - } - } - - if (callable is KtFunction) { - usages += FunctionDefinitionInfo(callable) - processInternalUsages(callable, usages) - } - } - } - } - - project.checkConflictsInteractively(conflicts) { - project.executeWriteCommand(text) { - val elementsToShorten = ArrayList() - usages.forEach { it.process(data, elementsToShorten) } - ShortenReferences.DEFAULT.process(elementsToShorten) - } - } - } - - private fun processExternalUsage( - conflicts: MultiMap, - refElement: PsiElement, - usages: ArrayList> - ) { - val callElement = refElement.getParentOfTypeAndBranch { calleeExpression } - if (callElement != null) { - val context = callElement.analyze(BodyResolveMode.PARTIAL) - val expressionToProcess = getArgumentExpressionToProcess(callElement, context) ?: return - - if (!data.isFirstParameter - && callElement is KtConstructorDelegationCall - && expressionToProcess !is KtLambdaExpression - && expressionToProcess !is KtSimpleNameExpression - && expressionToProcess !is KtCallableReferenceExpression) { - conflicts.putValue( - expressionToProcess, - "Following expression won't be processed since refactoring can't preserve its semantics: ${expressionToProcess.text}" - ) - return - } - - if (!checkThisExpressionsAreExplicatable(conflicts, context, expressionToProcess)) return - - if (data.isFirstParameter && expressionToProcess !is KtLambdaExpression) return - - usages += LambdaInfo(expressionToProcess) - return - } - - if (data.isFirstParameter) return - - val callableReference = refElement.getParentOfTypeAndBranch { callableReference } - if (callableReference != null) { - conflicts.putValue( - refElement, - "Callable reference transformation is not supported: " + StringUtil.htmlEmphasize(callableReference.text) - ) - return - } - } - - private fun getArgumentExpressionToProcess(callElement: KtCallElement, context: BindingContext): KtExpression? { - return callElement - .getArgumentByParameterIndex(data.functionParameterIndex, context) - .singleOrNull() - ?.getArgumentExpression() - ?.let { KtPsiUtil.safeDeparenthesize(it) } - } - - private fun checkThisExpressionsAreExplicatable(conflicts: MultiMap, context: BindingContext, expressionToProcess: KtExpression): Boolean { - for (thisExpr in expressionToProcess.collectDescendantsOfType()) { - if (thisExpr.getLabelName() != null) continue - val descriptor = context[BindingContext.REFERENCE_TARGET, thisExpr.instanceReference] ?: continue - if (explicateReceiverOf(descriptor) == "this") { - conflicts.putValue( - thisExpr, - "Following expression won't be processed since refactoring can't preserve its semantics: ${thisExpr.text}" - ) - return false - } - } - return true - } - - private fun processInternalUsages(callable: KtFunction, usages: ArrayList>) { - val body = when (callable) { - is KtConstructor<*> -> callable.containingClassOrObject?.getBody() - else -> callable.bodyExpression - } - if (body != null) { - val functionParameter = callable.valueParameters.getOrNull(data.functionParameterIndex) ?: return - for (ref in ReferencesSearch.search(functionParameter, LocalSearchScope(body))) { - val element = ref.element as? KtSimpleNameExpression ?: continue - val callExpression = element.getParentOfTypeAndBranch { calleeExpression } - if (callExpression != null) { - usages += ParameterCallInfo(callExpression) - } - else if (!data.isFirstParameter) { - usages += InternalReferencePassInfo(element) - } - } - } - } - } - - class ConversionData( - val typeParameterIndex: Int, - val functionParameterIndex: Int, - val lambdaType: KotlinType, - val function: KtFunction - ) { - val isFirstParameter: Boolean get() = typeParameterIndex == 0 - val functionDescriptor by lazy { function.unsafeResolveToDescriptor() as FunctionDescriptor } - } - - private fun KtTypeReference.getConversionData(): ConversionData? { - val parameter = parent as? KtParameter ?: return null - val functionType = parameter.getParentOfTypeAndBranch { parameterList } ?: return null - if (functionType.receiverTypeReference != null) return null - val lambdaType = functionType.getAbbreviatedTypeOrType(functionType.analyze(BodyResolveMode.PARTIAL)) ?: return null - val containingParameter = (functionType.parent as? KtTypeReference)?.parent as? KtParameter ?: return null - val ownerFunction = containingParameter.ownerFunction as? KtFunction ?: return null - val typeParameterIndex = functionType.parameters.indexOf(parameter) - val functionParameterIndex = ownerFunction.valueParameters.indexOf(containingParameter) - return ConversionData(typeParameterIndex, functionParameterIndex, lambdaType, ownerFunction) - } - - override fun startInWriteAction(): Boolean = false - - override fun applicabilityRange(element: KtTypeReference): TextRange? { - val data = element.getConversionData() ?: return null - - val elementBefore = data.function.valueParameters[data.functionParameterIndex].typeReference!!.typeElement as KtFunctionType - val elementAfter = elementBefore.copied().apply { - setReceiverTypeReference(element) - parameterList!!.removeParameter(data.typeParameterIndex) - } - text = "Convert '${elementBefore.text}' to '${elementAfter.text}'" - - return element.textRange - } - - override fun applyTo(element: KtTypeReference, editor: Editor?) { - element.getConversionData()?.let { Converter(it).run() } - } -} diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt index b7eb85efc2c..5044cc70520 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt @@ -38,6 +38,7 @@ import org.jetbrains.kotlin.idea.references.KtSimpleReference import org.jetbrains.kotlin.idea.runSynchronouslyWithProgress import org.jetbrains.kotlin.idea.search.usagesSearch.searchReferencesOrMethodReferences import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.idea.util.application.progressIndicatorNullable import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* @@ -125,7 +126,7 @@ class ConvertFunctionTypeReceiverToParameterIntention : SelfTargetingRangeIntent runReadAction { val progressStep = 1.0/callables.size for ((i, callable) in callables.withIndex()) { - ProgressManager.getInstance().progressIndicator.fraction = (i + 1) * progressStep + ProgressManager.getInstance().progressIndicatorNullable!!.fraction = (i + 1) * progressStep if (callable !is KtFunction) continue diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt.181 b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt.181 deleted file mode 100644 index f9b059be672..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertFunctionTypeReceiverToParameterIntention.kt.181 +++ /dev/null @@ -1,222 +0,0 @@ -/* - * 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.intentions - -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.progress.ProgressManager -import com.intellij.openapi.util.TextRange -import com.intellij.psi.PsiElement -import com.intellij.psi.search.LocalSearchScope -import com.intellij.psi.search.searches.ReferencesSearch -import com.intellij.refactoring.util.RefactoringUIUtil -import com.intellij.util.containers.MultiMap -import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor -import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde -import org.jetbrains.kotlin.idea.core.* -import org.jetbrains.kotlin.idea.refactoring.CallableRefactoring -import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively -import org.jetbrains.kotlin.idea.refactoring.getAffectedCallables -import org.jetbrains.kotlin.idea.references.KtSimpleReference -import org.jetbrains.kotlin.idea.runSynchronouslyWithProgress -import org.jetbrains.kotlin.idea.search.usagesSearch.searchReferencesOrMethodReferences -import org.jetbrains.kotlin.idea.util.application.executeWriteCommand -import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.* -import org.jetbrains.kotlin.psi.typeRefHelpers.setReceiverTypeReference -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.bindingContextUtil.getAbbreviatedTypeOrType -import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getArgumentByParameterIndex -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.types.KotlinType - -class ConvertFunctionTypeReceiverToParameterIntention : SelfTargetingRangeIntention( - KtTypeReference::class.java, - "Convert function type receiver to parameter" -) { - class ConversionData( - val functionParameterIndex: Int, - val lambdaReceiverType: KotlinType, - val function: KtFunction - ) { - val functionDescriptor by lazy { function.unsafeResolveToDescriptor() as FunctionDescriptor } - } - - class FunctionDefinitionInfo(element: KtFunction) : AbstractProcessableUsageInfo(element) { - override fun process(data: ConversionData, elementsToShorten: MutableList) { - val function = element ?: return - val functionParameter = function.valueParameters.getOrNull(data.functionParameterIndex) ?: return - val functionType = functionParameter.typeReference?.typeElement as? KtFunctionType ?: return - val functionTypeParameterList = functionType.parameterList ?: return - val functionTypeReceiver = functionType.receiverTypeReference ?: return - val parameterToAdd = KtPsiFactory(project).createFunctionTypeParameter(functionTypeReceiver) - functionTypeParameterList.addParameterBefore(parameterToAdd, functionTypeParameterList.parameters.firstOrNull()) - functionType.setReceiverTypeReference(null) - } - } - - class ParameterCallInfo(element: KtCallExpression) : AbstractProcessableUsageInfo(element) { - override fun process(data: ConversionData, elementsToShorten: MutableList) { - val callExpression = element ?: return - val qualifiedExpression = callExpression.getQualifiedExpressionForSelector() ?: return - val receiverExpression = qualifiedExpression.receiverExpression - val argumentList = callExpression.getOrCreateValueArgumentList() - argumentList.addArgumentBefore(KtPsiFactory(project).createArgument(receiverExpression), argumentList.arguments.firstOrNull()) - qualifiedExpression.replace(callExpression) - } - } - - class LambdaInfo(element: KtLambdaExpression) : AbstractProcessableUsageInfo(element) { - override fun process(data: ConversionData, elementsToShorten: MutableList) { - val lambda = element?.functionLiteral ?: return - val context = lambda.analyze(BodyResolveMode.PARTIAL) - - val psiFactory = KtPsiFactory(project) - - val validator = CollectingNameValidator( - lambda.valueParameters.mapNotNull { it.name }, - NewDeclarationNameValidator(lambda.bodyExpression!!, null, NewDeclarationNameValidator.Target.VARIABLES) - ) - val newParameterName = KotlinNameSuggester.suggestNamesByType(data.lambdaReceiverType, validator, "p").first() - val newParameterRefExpression = psiFactory.createExpression(newParameterName) - - lambda.forEachDescendantOfType { - val thisTarget = context[BindingContext.REFERENCE_TARGET, it.instanceReference] ?: return@forEachDescendantOfType - if (DescriptorToSourceUtilsIde.getAnyDeclaration(project, thisTarget) == lambda) { - it.replace(newParameterRefExpression) - } - } - - val lambdaParameterList = lambda.getOrCreateParameterList() - val parameterToAdd = psiFactory.createLambdaParameterList(newParameterName).parameters.first() - lambdaParameterList.addParameterBefore(parameterToAdd, lambdaParameterList.parameters.firstOrNull()) - } - } - - private inner class Converter( - private val data: ConversionData - ) : CallableRefactoring(data.function.project, data.functionDescriptor, text) { - override fun performRefactoring(descriptorsForChange: Collection) { - val callables = getAffectedCallables(project, descriptorsForChange) - - val conflicts = MultiMap() - - val usages = ArrayList>() - - project.runSynchronouslyWithProgress("Looking for usages and conflicts...", true) { - runReadAction { - val progressStep = 1.0/callables.size - for ((i, callable) in callables.withIndex()) { - ProgressManager.getInstance().progressIndicator!!.fraction = (i + 1) * progressStep - - if (callable !is KtFunction) continue - - if (!checkModifiable(callable)) { - val renderedCallable = RefactoringUIUtil.getDescription(callable, true).capitalize() - conflicts.putValue(callable, "Can't modify $renderedCallable") - } - - for (ref in callable.searchReferencesOrMethodReferences()) { - if (ref !is KtSimpleReference<*>) continue - processExternalUsage(ref, usages) - } - - usages += FunctionDefinitionInfo(callable) - - processInternalUsages(callable, usages) - } - } - } - - project.checkConflictsInteractively(conflicts) { - project.executeWriteCommand(text) { - val elementsToShorten = ArrayList() - usages.forEach { it.process(data, elementsToShorten) } - ShortenReferences.DEFAULT.process(elementsToShorten) - } - } - } - - private fun processExternalUsage(ref: KtSimpleReference<*>, usages: java.util.ArrayList>) { - val callElement = ref.element.getParentOfTypeAndBranch { calleeExpression } ?: return - val context = callElement.analyze(BodyResolveMode.PARTIAL) - val expressionToProcess = callElement - .getArgumentByParameterIndex(data.functionParameterIndex, context) - .singleOrNull() - ?.getArgumentExpression() - ?.let { KtPsiUtil.safeDeparenthesize(it) } - ?: return - if (expressionToProcess is KtLambdaExpression) { - usages += LambdaInfo(expressionToProcess) - } - } - - private fun processInternalUsages(callable: KtFunction, usages: java.util.ArrayList>) { - val body = when (callable) { - is KtConstructor<*> -> callable.containingClassOrObject?.getBody() - else -> callable.bodyExpression - } - if (body != null) { - val functionParameter = callable.valueParameters.getOrNull(data.functionParameterIndex) ?: return - for (ref in ReferencesSearch.search(functionParameter, LocalSearchScope(body))) { - val element = ref.element as? KtSimpleNameExpression ?: continue - val callExpression = element.getParentOfTypeAndBranch { calleeExpression } ?: continue - usages += ParameterCallInfo(callExpression) - } - } - } - } - - private fun KtTypeReference.getConversionData(): ConversionData? { - val functionTypeReceiver = parent as? KtFunctionTypeReceiver ?: return null - val functionType = functionTypeReceiver.parent as? KtFunctionType ?: return null - val lambdaReceiverType = functionType - .getAbbreviatedTypeOrType(functionType.analyze(BodyResolveMode.PARTIAL)) - ?.getReceiverTypeFromFunctionType() - ?: return null - val containingParameter = (functionType.parent as? KtTypeReference)?.parent as? KtParameter ?: return null - val ownerFunction = containingParameter.ownerFunction as? KtFunction ?: return null - val functionParameterIndex = ownerFunction.valueParameters.indexOf(containingParameter) - return ConversionData(functionParameterIndex, lambdaReceiverType, ownerFunction) - } - - override fun startInWriteAction(): Boolean = false - - override fun applicabilityRange(element: KtTypeReference): TextRange? { - val data = element.getConversionData() ?: return null - - val elementBefore = data.function.valueParameters[data.functionParameterIndex].typeReference!!.typeElement as KtFunctionType - val elementAfter = elementBefore.copied().apply { - parameterList!!.addParameterBefore( - KtPsiFactory(element).createFunctionTypeParameter(element), - parameterList!!.parameters.firstOrNull() - ) - setReceiverTypeReference(null) - } - text = "Convert '${elementBefore.text}' to '${elementAfter.text}'" - - return element.textRange - } - - override fun applyTo(element: KtTypeReference, editor: Editor?) { - element.getConversionData()?.let { Converter(it).run() } - } -} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyToFunctionIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyToFunctionIntention.kt index f4cef3242f0..4149f1f0e52 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyToFunctionIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyToFunctionIntention.kt @@ -35,6 +35,7 @@ import org.jetbrains.kotlin.idea.references.KtReference import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.idea.runSynchronouslyWithProgress import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.idea.util.application.progressIndicatorNullable import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.load.java.JvmAbi @@ -97,7 +98,7 @@ class ConvertPropertyToFunctionIntention : SelfTargetingIntention(Kt runReadAction { val progressStep = 1.0/callables.size for ((i, callable) in callables.withIndex()) { - ProgressManager.getInstance().progressIndicator.fraction = (i + 1)*progressStep + ProgressManager.getInstance().progressIndicatorNullable!!.fraction = (i + 1)*progressStep if (callable !is PsiNamedElement) continue diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyToFunctionIntention.kt.181 b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyToFunctionIntention.kt.181 deleted file mode 100644 index 93d464dc37a..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertPropertyToFunctionIntention.kt.181 +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright 2010-2015 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.intentions - -import com.intellij.codeInsight.intention.LowPriorityAction -import com.intellij.openapi.editor.Editor -import com.intellij.openapi.progress.ProgressManager -import com.intellij.openapi.project.Project -import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.* -import com.intellij.psi.search.searches.ReferencesSearch -import com.intellij.refactoring.util.RefactoringUIUtil -import com.intellij.util.containers.MultiMap -import org.jetbrains.kotlin.asJava.namedUnwrappedElement -import org.jetbrains.kotlin.descriptors.CallableDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny -import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde -import org.jetbrains.kotlin.idea.refactoring.* -import org.jetbrains.kotlin.idea.references.KtReference -import org.jetbrains.kotlin.idea.references.KtSimpleNameReference -import org.jetbrains.kotlin.idea.runSynchronouslyWithProgress -import org.jetbrains.kotlin.idea.util.application.executeWriteCommand -import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.incremental.components.NoLookupLocation -import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.psi.KtCallableReferenceExpression -import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -import org.jetbrains.kotlin.psi.psiUtil.siblings -import org.jetbrains.kotlin.resolve.calls.callUtil.getCall -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import org.jetbrains.kotlin.resolve.scopes.utils.findFunction -import java.util.* - -class ConvertPropertyToFunctionIntention : SelfTargetingIntention(KtProperty::class.java, "Convert property to function"), LowPriorityAction { - private inner class Converter( - project: Project, - descriptor: CallableDescriptor - ): CallableRefactoring(project, descriptor, text) { - private val newName: String = JvmAbi.getterName(callableDescriptor.name.asString()) - - private fun convertProperty(originalProperty: KtProperty, psiFactory: KtPsiFactory) { - val property = originalProperty.copy() as KtProperty - val getter = property.getter - - val sampleFunction = psiFactory.createFunction("fun foo() {\n\n}") - - property.valOrVarKeyword.replace(sampleFunction.funKeyword!!) - property.addAfter(psiFactory.createParameterList("()"), property.nameIdentifier) - if (property.initializer == null) { - if (getter != null) { - val dropGetterTo = (getter.equalsToken ?: getter.bodyExpression) - ?.siblings(forward = false, withItself = false) - ?.firstOrNull { it !is PsiWhiteSpace } - getter.deleteChildRange(getter.firstChild, dropGetterTo) - - val dropPropertyFrom = getter - .siblings(forward = false, withItself = false) - .first { it !is PsiWhiteSpace } - .nextSibling - property.deleteChildRange(dropPropertyFrom, getter.prevSibling) - } - } - property.setName(newName) - - originalProperty.replace(psiFactory.createFunction(property.text)) - } - - override fun performRefactoring(descriptorsForChange: Collection) { - val propertyName = callableDescriptor.name.asString() - val nameChanged = propertyName != newName - val getterName = JvmAbi.getterName(callableDescriptor.name.asString()) - val conflicts = MultiMap() - val callables = getAffectedCallables(project, descriptorsForChange) - val kotlinRefsToReplaceWithCall = ArrayList() - val refsToRename = ArrayList() - val javaRefsToReplaceWithCall = ArrayList() - - project.runSynchronouslyWithProgress("Looking for usages and conflicts...", true) { - runReadAction { - val progressStep = 1.0/callables.size - for ((i, callable) in callables.withIndex()) { - ProgressManager.getInstance().progressIndicator!!.fraction = (i + 1) * progressStep - - if (callable !is PsiNamedElement) continue - - if (!checkModifiable(callable)) { - val renderedCallable = RefactoringUIUtil.getDescription(callable, true).capitalize() - conflicts.putValue(callable, "Can't modify $renderedCallable") - } - - if (callable is KtProperty) { - callableDescriptor.getContainingScope() - ?.findFunction(callableDescriptor.name, NoLookupLocation.FROM_IDE) { it.valueParameters.isEmpty() } - ?.let { DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) } - ?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } } - } - else if (callable is PsiMethod) { - callable.containingClass - ?.findMethodsByName(propertyName, true) - // as is necessary here: see KT-10386 - ?.firstOrNull { it.parameterList.parametersCount == 0 && !callables.contains(it.namedUnwrappedElement as PsiElement?) } - ?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } } - } - - val usages = ReferencesSearch.search(callable) - for (usage in usages) { - if (usage is KtReference) { - if (usage is KtSimpleNameReference) { - val expression = usage.expression - if (expression.getCall(expression.analyze(BodyResolveMode.PARTIAL)) != null - && expression.getStrictParentOfType() == null) { - kotlinRefsToReplaceWithCall.add(expression) - } - else if (nameChanged) { - refsToRename.add(usage) - } - } - else { - val refElement = usage.element - conflicts.putValue( - refElement, - "Unrecognized reference will be skipped: " + StringUtil.htmlEmphasize(refElement.text) - ) - } - continue - } - - val refElement = usage.element - - if (refElement.text.endsWith(getterName)) continue - - if (usage is PsiJavaReference) { - if (usage.resolve() is PsiField && usage is PsiReferenceExpression) { - javaRefsToReplaceWithCall.add(usage) - } - continue - } - - conflicts.putValue( - refElement, - "Can't replace foreign reference with call expression: " + StringUtil.htmlEmphasize(refElement.text) - ) - } - } - } - } - - project.checkConflictsInteractively(conflicts) { - project.executeWriteCommand(text) { - val kotlinPsiFactory = KtPsiFactory(project) - val javaPsiFactory = PsiElementFactory.SERVICE.getInstance(project) - val newKotlinCallExpr = kotlinPsiFactory.createExpression("$newName()") - - kotlinRefsToReplaceWithCall.forEach { it.replace(newKotlinCallExpr) } - refsToRename.forEach { it.handleElementRename(newName) } - javaRefsToReplaceWithCall.forEach { - val getterRef = it.handleElementRename(newName) - getterRef.replace(javaPsiFactory.createExpressionFromText("${getterRef.text}()", null)) - } - callables.forEach { - when (it) { - is KtProperty -> convertProperty(it, kotlinPsiFactory) - is PsiMethod -> it.name = newName - } - } - } - } - } - } - - override fun startInWriteAction(): Boolean = false - - override fun isApplicableTo(element: KtProperty, caretOffset: Int): Boolean { - val identifier = element.nameIdentifier ?: return false - if (!identifier.textRange.containsOffset(caretOffset)) return false - return element.delegate == null && !element.isVar && !element.isLocal && (element.initializer == null || element.getter == null) - } - - override fun applyTo(element: KtProperty, editor: Editor?) { - val descriptor = element.resolveToDescriptorIfAny(BodyResolveMode.FULL) as? CallableDescriptor ?: return - Converter(element.project, descriptor).run() - } -}