Migration to expect/actual: some intentions
This commit is contained in:
@@ -20,7 +20,7 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.refactoring.withHeaderImplementations
|
||||
import org.jetbrains.kotlin.idea.refactoring.withExpectedActuals
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.util.OperatorChecks
|
||||
@@ -34,7 +34,7 @@ class AddOperatorModifierIntention : SelfTargetingRangeIntention<KtNamedFunction
|
||||
}
|
||||
|
||||
override fun applyTo(element: KtNamedFunction, editor: Editor?) {
|
||||
element.withHeaderImplementations().forEach { it.addModifier(KtTokens.OPERATOR_KEYWORD) }
|
||||
element.withExpectedActuals().forEach { it.addModifier(KtTokens.OPERATOR_KEYWORD) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinChangeSignatu
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinMethodDescriptor
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.modify
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.runChangeSignature
|
||||
import org.jetbrains.kotlin.idea.refactoring.resolveToHeaderDescriptorIfPossible
|
||||
import org.jetbrains.kotlin.idea.refactoring.resolveToExpectedDescriptorIfPossible
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
@@ -52,7 +52,7 @@ class ConvertParameterToReceiverIntention : SelfTargetingIntention<KtParameter>(
|
||||
override fun applyTo(element: KtParameter, editor: Editor?) {
|
||||
val function = element.getStrictParentOfType<KtNamedFunction>() ?: return
|
||||
val parameterIndex = function.valueParameters.indexOf(element)
|
||||
val descriptor = function.resolveToHeaderDescriptorIfPossible() as? FunctionDescriptor ?: return
|
||||
val descriptor = function.resolveToExpectedDescriptorIfPossible() as? FunctionDescriptor ?: return
|
||||
runChangeSignature(element.project, descriptor, configureChangeSignature(parameterIndex), element, text)
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -28,7 +28,7 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.getOrCreateValueParameterList
|
||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.*
|
||||
import org.jetbrains.kotlin.idea.refactoring.resolveToHeaderDescriptorIfPossible
|
||||
import org.jetbrains.kotlin.idea.refactoring.resolveToExpectedDescriptorIfPossible
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
@@ -61,7 +61,7 @@ class ConvertReceiverToParameterIntention : SelfTargetingOffsetIndependentIntent
|
||||
|
||||
override fun applyTo(element: KtTypeReference, editor: Editor?) {
|
||||
val function = element.parent as? KtNamedFunction ?: return
|
||||
val descriptor = function.resolveToHeaderDescriptorIfPossible() as FunctionDescriptor
|
||||
val descriptor = function.resolveToExpectedDescriptorIfPossible() as FunctionDescriptor
|
||||
|
||||
val project = function.project
|
||||
|
||||
@@ -102,7 +102,7 @@ class ConvertReceiverToParameterIntention : SelfTargetingOffsetIndependentIntent
|
||||
if (!brokenOff) {
|
||||
runChangeSignature(
|
||||
element.project,
|
||||
function.resolveToHeaderDescriptorIfPossible() as FunctionDescriptor,
|
||||
function.resolveToExpectedDescriptorIfPossible() as FunctionDescriptor,
|
||||
configureChangeSignature(newName),
|
||||
function.receiverTypeReference!!,
|
||||
text
|
||||
|
||||
+20
-19
@@ -38,7 +38,7 @@ import org.jetbrains.kotlin.idea.highlighter.markers.isExpectedOrExpectedClassMe
|
||||
import org.jetbrains.kotlin.idea.highlighter.markers.liftToExpected
|
||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.getReturnTypeReference
|
||||
import org.jetbrains.kotlin.idea.refactoring.withHeaderImplementations
|
||||
import org.jetbrains.kotlin.idea.refactoring.withExpectedActuals
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.util.ImportInsertHelper
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
@@ -61,7 +61,7 @@ class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallable
|
||||
}
|
||||
|
||||
override fun applicabilityRange(element: KtCallableDeclaration): TextRange? {
|
||||
if (!element.withHeaderImplementations().all { it is KtCallableDeclaration && isApplicable(it) }) return null
|
||||
if (!element.withExpectedActuals().all { it is KtCallableDeclaration && isApplicable(it) }) return null
|
||||
return (element.nameIdentifier ?: return null).textRange
|
||||
}
|
||||
|
||||
@@ -70,16 +70,16 @@ class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallable
|
||||
//TODO: local class
|
||||
|
||||
override fun applyTo(element: KtCallableDeclaration, editor: Editor?) {
|
||||
var allowHeader = true
|
||||
var allowExpected = true
|
||||
|
||||
element.liftToExpected()?.actualsForExpected()?.let {
|
||||
if (it.isEmpty()) {
|
||||
allowHeader = askIfHeaderIsAllowed(element.containingKtFile)
|
||||
allowExpected = askIfExpectedIsAllowed(element.containingKtFile)
|
||||
}
|
||||
}
|
||||
|
||||
runWriteAction {
|
||||
val (extension, bodyToSelect) = createExtensionCallableAndPrepareBodyToSelect(element, allowHeader)
|
||||
val (extension, bodyToSelect) = createExtensionCallableAndPrepareBodyToSelect(element, allowExpected)
|
||||
|
||||
editor?.apply {
|
||||
unblockDocument()
|
||||
@@ -106,12 +106,12 @@ class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallable
|
||||
|
||||
private fun processSingleDeclaration(
|
||||
element: KtCallableDeclaration,
|
||||
allowHeader: Boolean
|
||||
allowExpected: Boolean
|
||||
): Pair<KtCallableDeclaration, KtExpression?> {
|
||||
val descriptor = element.unsafeResolveToDescriptor()
|
||||
val containingClass = descriptor.containingDeclaration as ClassDescriptor
|
||||
|
||||
val isEffectiveHeader = allowHeader && element.isExpectedOrExpectedClassMember()
|
||||
val isEffectivelyExpected = allowExpected && element.isExpectedOrExpectedClassMember()
|
||||
|
||||
val file = element.containingKtFile
|
||||
val project = file.project
|
||||
@@ -157,8 +157,9 @@ class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallable
|
||||
extension.modifierList?.getModifier(KtTokens.OPEN_KEYWORD)?.delete()
|
||||
extension.modifierList?.getModifier(KtTokens.FINAL_KEYWORD)?.delete()
|
||||
|
||||
if (isEffectiveHeader && !extension.hasModifier(KtTokens.HEADER_KEYWORD))
|
||||
extension.addModifier(KtTokens.HEADER_KEYWORD)
|
||||
if (isEffectivelyExpected && !extension.hasExpectModifier()) {
|
||||
extension.addModifier(KtTokens.EXPECT_KEYWORD)
|
||||
}
|
||||
|
||||
var bodyToSelect: KtExpression? = null
|
||||
|
||||
@@ -179,7 +180,7 @@ class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallable
|
||||
|
||||
when (extension) {
|
||||
is KtFunction -> {
|
||||
if (!extension.hasBody() && !isEffectiveHeader) {
|
||||
if (!extension.hasBody() && !isEffectivelyExpected) {
|
||||
//TODO: methods in PSI for setBody
|
||||
extension.add(psiFactory.createBlock(bodyText))
|
||||
selectBody(extension)
|
||||
@@ -189,7 +190,7 @@ class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallable
|
||||
is KtProperty -> {
|
||||
val templateProperty = psiFactory.createDeclaration<KtProperty>("var v: Any\nget()=$bodyText\nset(value){\n$bodyText\n}")
|
||||
|
||||
if (!isEffectiveHeader) {
|
||||
if (!isEffectivelyExpected) {
|
||||
val templateGetter = templateProperty.getter!!
|
||||
val templateSetter = templateProperty.setter!!
|
||||
|
||||
@@ -244,13 +245,13 @@ class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallable
|
||||
return extension to bodyToSelect
|
||||
}
|
||||
|
||||
private fun askIfHeaderIsAllowed(file: KtFile): Boolean {
|
||||
private fun askIfExpectedIsAllowed(file: KtFile): Boolean {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||
return file.allChildren.any { it is PsiComment && it.text.trim() == "// ALLOW_HEADER_WITHOUT_IMPLS" }
|
||||
}
|
||||
|
||||
return Messages.showYesNoDialog(
|
||||
"Do you want to make new extension a header declaration?",
|
||||
"Do you want to make new extension an expected declaration?",
|
||||
text,
|
||||
Messages.getQuestionIcon()
|
||||
) == Messages.YES
|
||||
@@ -258,18 +259,18 @@ class ConvertMemberToExtensionIntention : SelfTargetingRangeIntention<KtCallable
|
||||
|
||||
private fun createExtensionCallableAndPrepareBodyToSelect(
|
||||
element: KtCallableDeclaration,
|
||||
allowHeader: Boolean = true
|
||||
allowExpected: Boolean = true
|
||||
): Pair<KtCallableDeclaration, KtExpression?> {
|
||||
val headerDeclaration = element.liftToExpected() as? KtCallableDeclaration
|
||||
if (headerDeclaration != null) {
|
||||
element.withHeaderImplementations().filterIsInstance<KtCallableDeclaration>().forEach {
|
||||
val expectedDeclaration = element.liftToExpected() as? KtCallableDeclaration
|
||||
if (expectedDeclaration != null) {
|
||||
element.withExpectedActuals().filterIsInstance<KtCallableDeclaration>().forEach {
|
||||
if (it != element) {
|
||||
processSingleDeclaration(it, allowHeader)
|
||||
processSingleDeclaration(it, allowExpected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return processSingleDeclaration(element, allowHeader)
|
||||
return processSingleDeclaration(element, allowExpected)
|
||||
}
|
||||
|
||||
private fun newTypeParameterList(member: KtCallableDeclaration): KtTypeParameterList? {
|
||||
|
||||
@@ -967,13 +967,13 @@ fun KtNamedDeclaration.isCompanionMemberOf(klass: KtClassOrObject): Boolean {
|
||||
return containingObject.isCompanion() && containingObject.containingClassOrObject == klass
|
||||
}
|
||||
|
||||
internal fun KtDeclaration.withHeaderImplementations(): List<KtDeclaration> {
|
||||
internal fun KtDeclaration.withExpectedActuals(): List<KtDeclaration> {
|
||||
val header = liftToExpected() ?: return listOf(this)
|
||||
val implementations = header.actualsForExpected()
|
||||
return listOf(header) + implementations
|
||||
}
|
||||
|
||||
internal fun KtDeclaration.resolveToHeaderDescriptorIfPossible(): DeclarationDescriptor {
|
||||
internal fun KtDeclaration.resolveToExpectedDescriptorIfPossible(): DeclarationDescriptor {
|
||||
val descriptor = unsafeResolveToDescriptor()
|
||||
return descriptor.liftToExpected() ?: descriptor
|
||||
}
|
||||
+2
-2
@@ -45,7 +45,7 @@ import org.jetbrains.kotlin.idea.highlighter.markers.liftToExpected
|
||||
import org.jetbrains.kotlin.idea.refactoring.checkSuperMethods
|
||||
import org.jetbrains.kotlin.idea.refactoring.formatClass
|
||||
import org.jetbrains.kotlin.idea.refactoring.formatFunction
|
||||
import org.jetbrains.kotlin.idea.refactoring.withHeaderImplementations
|
||||
import org.jetbrains.kotlin.idea.refactoring.withExpectedActuals
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
|
||||
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters
|
||||
@@ -86,7 +86,7 @@ class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
|
||||
fun getSearchInfo(element: PsiElement) = NonCodeUsageSearchInfo(getIgnoranceCondition(), element)
|
||||
|
||||
fun searchKotlinDeclarationReferences(declaration: KtDeclaration): Sequence<PsiReference> {
|
||||
val elementsToSearch = if (declaration is KtParameter) declaration.withHeaderImplementations() else listOf(declaration)
|
||||
val elementsToSearch = if (declaration is KtParameter) declaration.withExpectedActuals() else listOf(declaration)
|
||||
return elementsToSearch.asSequence().flatMap {
|
||||
val searchParameters = KotlinReferencesSearchParameters(
|
||||
it,
|
||||
|
||||
Reference in New Issue
Block a user