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