FIR IDE: extract common logic idea.core.overrideImplement
Also rename OverrideImplementMemberHandler to GenerateMemberHandler to align with the naming of its member functions.
This commit is contained in:
committed by
TeamCityServer
parent
06ba143afe
commit
34387e228f
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
|
||||
fun <T : KtDeclaration> insertMembersAfterAndReformat(
|
||||
editor: Editor?,
|
||||
classOrObject: KtClassOrObject,
|
||||
members: Collection<T>,
|
||||
anchor: PsiElement? = null,
|
||||
getAnchor: (KtDeclaration) -> PsiElement? = { null },
|
||||
): List<T> {
|
||||
val codeStyleManager = CodeStyleManager.getInstance(classOrObject.project)
|
||||
return runWriteAction {
|
||||
val insertedMembersElementPointers = insertMembersAfter(editor, classOrObject, members, anchor, getAnchor)
|
||||
val firstElement = insertedMembersElementPointers.firstOrNull() ?: return@runWriteAction emptyList()
|
||||
|
||||
fun insertedMembersElements() = insertedMembersElementPointers.mapNotNull { it.element }
|
||||
|
||||
ShortenReferences.DEFAULT.process(insertedMembersElements())
|
||||
if (editor != null) {
|
||||
firstElement.element?.let { moveCaretIntoGeneratedElement(editor, it) }
|
||||
}
|
||||
|
||||
insertedMembersElementPointers.onEach { it.element?.let { element -> codeStyleManager.reformat(element) } }
|
||||
insertedMembersElements()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : KtDeclaration> insertMember(editor: Editor?, classOrObject: KtClassOrObject, declaration: T, anchor: PsiElement? = null): T {
|
||||
return insertMembersAfterAndReformat(editor, classOrObject, listOf(declaration), anchor).single()
|
||||
}
|
||||
+13
-73
@@ -16,28 +16,18 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.core.overrideImplement
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService
|
||||
import com.intellij.codeInsight.hint.HintManager
|
||||
import com.intellij.ide.util.MemberChooser
|
||||
import com.intellij.lang.LanguageCodeInsightActionHandler
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.DialogWrapper
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.insertMembersAfter
|
||||
import org.jetbrains.kotlin.idea.core.insertMembersAfterAndReformat
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.prevSiblingOfSameType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -45,74 +35,24 @@ import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.util.findCallableMemberBySignature
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
abstract class OverrideImplementMembersHandler : LanguageCodeInsightActionHandler {
|
||||
abstract class GenerateMembersHandler : AbstractGenerateMembersHandler<OverrideMemberChooserObject>() {
|
||||
|
||||
fun collectMembersToGenerate(classOrObject: KtClassOrObject): Collection<OverrideMemberChooserObject> {
|
||||
override fun collectMembersToGenerate(classOrObject: KtClassOrObject): Collection<OverrideMemberChooserObject> {
|
||||
val descriptor = classOrObject.resolveToDescriptorIfAny() ?: return emptySet()
|
||||
return collectMembersToGenerate(descriptor, classOrObject.project)
|
||||
}
|
||||
|
||||
protected abstract fun collectMembersToGenerate(descriptor: ClassDescriptor, project: Project): Collection<OverrideMemberChooserObject>
|
||||
|
||||
private fun showOverrideImplementChooser(
|
||||
project: Project,
|
||||
members: Array<OverrideMemberChooserObject>
|
||||
): MemberChooser<OverrideMemberChooserObject>? {
|
||||
val chooser = MemberChooser(members, true, true, project)
|
||||
chooser.title = getChooserTitle()
|
||||
chooser.show()
|
||||
if (chooser.exitCode != DialogWrapper.OK_EXIT_CODE) return null
|
||||
return chooser
|
||||
override fun generateMembers(
|
||||
editor: Editor,
|
||||
classOrObject: KtClassOrObject,
|
||||
selectedElements: Collection<OverrideMemberChooserObject>,
|
||||
copyDoc: Boolean
|
||||
) {
|
||||
return Companion.generateMembers(editor, classOrObject, selectedElements, copyDoc)
|
||||
}
|
||||
|
||||
protected abstract fun getChooserTitle(): String
|
||||
|
||||
protected open fun isValidForClass(classOrObject: KtClassOrObject) = true
|
||||
|
||||
override fun isValidFor(editor: Editor, file: PsiFile): Boolean {
|
||||
if (file !is KtFile) return false
|
||||
val elementAtCaret = file.findElementAt(editor.caretModel.offset)
|
||||
val classOrObject = elementAtCaret?.getNonStrictParentOfType<KtClassOrObject>()
|
||||
return classOrObject != null && isValidForClass(classOrObject)
|
||||
}
|
||||
|
||||
protected abstract fun getNoMembersFoundHint(): String
|
||||
|
||||
fun invoke(project: Project, editor: Editor, file: PsiFile, implementAll: Boolean) {
|
||||
val elementAtCaret = file.findElementAt(editor.caretModel.offset)
|
||||
val classOrObject = elementAtCaret?.getNonStrictParentOfType<KtClassOrObject>() ?: return
|
||||
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return
|
||||
|
||||
val members = collectMembersToGenerate(classOrObject)
|
||||
if (members.isEmpty() && !implementAll) {
|
||||
HintManager.getInstance().showErrorHint(editor, getNoMembersFoundHint())
|
||||
return
|
||||
}
|
||||
|
||||
val copyDoc: Boolean
|
||||
val selectedElements: Collection<OverrideMemberChooserObject>
|
||||
if (implementAll) {
|
||||
selectedElements = members
|
||||
copyDoc = false
|
||||
} else {
|
||||
val chooser = showOverrideImplementChooser(project, members.toTypedArray()) ?: return
|
||||
selectedElements = chooser.selectedElements ?: return
|
||||
copyDoc = chooser.isCopyJavadoc
|
||||
}
|
||||
if (selectedElements.isEmpty()) return
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||
|
||||
generateMembers(editor, classOrObject, selectedElements, copyDoc)
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
|
||||
invoke(project, editor, file, implementAll = ApplicationManager.getApplication().isUnitTestMode)
|
||||
}
|
||||
|
||||
override fun startInWriteAction(): Boolean = false
|
||||
|
||||
companion object {
|
||||
fun generateMembers(
|
||||
editor: Editor?,
|
||||
@@ -124,7 +64,7 @@ abstract class OverrideImplementMembersHandler : LanguageCodeInsightActionHandle
|
||||
|
||||
val classBody = classOrObject.body
|
||||
if (classBody == null) {
|
||||
insertMembersAfter(editor, classOrObject, selectedMemberDescriptors.keys)
|
||||
insertMembersAfterAndReformat(editor, classOrObject, selectedMemberDescriptors.keys)
|
||||
return
|
||||
}
|
||||
val offset = editor?.caretModel?.offset ?: classBody.startOffset
|
||||
@@ -132,7 +72,7 @@ abstract class OverrideImplementMembersHandler : LanguageCodeInsightActionHandle
|
||||
it.parent == classBody
|
||||
}
|
||||
if (offsetCursorElement != null && offsetCursorElement != classBody.rBrace) {
|
||||
insertMembersAfter(editor, classOrObject, selectedMemberDescriptors.keys)
|
||||
insertMembersAfterAndReformat(editor, classOrObject, selectedMemberDescriptors.keys)
|
||||
return
|
||||
}
|
||||
val classLeftBrace = classBody.lBrace
|
||||
@@ -173,7 +113,7 @@ abstract class OverrideImplementMembersHandler : LanguageCodeInsightActionHandle
|
||||
return lastElement
|
||||
}
|
||||
|
||||
insertMembersAfter(editor, classOrObject, selectedMemberDescriptors.keys) { getAnchor(it) }
|
||||
insertMembersAfterAndReformat(editor, classOrObject, selectedMemberDescriptors.keys) { getAnchor(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -22,8 +22,8 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.util.KotlinIdeaCoreBundle
|
||||
import org.jetbrains.kotlin.idea.util.expectedDescriptors
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.hasPrimaryConstructor
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
@@ -31,24 +31,24 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
import org.jetbrains.kotlin.resolve.OverrideResolver
|
||||
|
||||
open class ImplementMembersHandler : OverrideImplementMembersHandler(), IntentionAction {
|
||||
open class ImplementMembersHandler : GenerateMembersHandler(), IntentionAction {
|
||||
override fun collectMembersToGenerate(descriptor: ClassDescriptor, project: Project): Collection<OverrideMemberChooserObject> {
|
||||
return OverrideResolver.getMissingImplementations(descriptor)
|
||||
.map { OverrideMemberChooserObject.create(project, it, it, OverrideMemberChooserObject.BodyType.FROM_TEMPLATE) }
|
||||
.map { OverrideMemberChooserObject.create(project, it, it, BodyType.FROM_TEMPLATE) }
|
||||
}
|
||||
|
||||
override fun getChooserTitle() = KotlinIdeaCoreBundle.message("implement.members.handler.title")
|
||||
override fun getChooserTitle() = KotlinBundle.message("implement.members.handler.title")
|
||||
|
||||
override fun getNoMembersFoundHint() = KotlinIdeaCoreBundle.message("implement.members.handler.no.members.hint")
|
||||
override fun getNoMembersFoundHint() = KotlinBundle.message("implement.members.handler.no.members.hint")
|
||||
|
||||
override fun getText() = familyName
|
||||
override fun getFamilyName() = KotlinIdeaCoreBundle.message("implement.members.handler.family")
|
||||
override fun getFamilyName() = KotlinBundle.message("implement.members.handler.family")
|
||||
|
||||
override fun isAvailable(project: Project, editor: Editor, file: PsiFile) = isValidFor(editor, file)
|
||||
}
|
||||
|
||||
class ImplementAsConstructorParameter : ImplementMembersHandler() {
|
||||
override fun getText() = KotlinIdeaCoreBundle.message("action.text.implement.as.constructor.parameters")
|
||||
override fun getText() = KotlinBundle.message("action.text.implement.as.constructor.parameters")
|
||||
|
||||
override fun isValidForClass(classOrObject: KtClassOrObject): Boolean {
|
||||
if (classOrObject !is KtClass || classOrObject is KtEnumEntry || classOrObject.isInterface()) return false
|
||||
@@ -67,6 +67,6 @@ class ImplementAsConstructorParameter : ImplementMembersHandler() {
|
||||
override fun collectMembersToGenerate(descriptor: ClassDescriptor, project: Project): Collection<OverrideMemberChooserObject> {
|
||||
return OverrideResolver.getMissingImplementations(descriptor)
|
||||
.filterIsInstance<PropertyDescriptor>()
|
||||
.map { OverrideMemberChooserObject.create(project, it, it, OverrideMemberChooserObject.BodyType.FROM_TEMPLATE, true) }
|
||||
.map { OverrideMemberChooserObject.create(project, it, it, BodyType.FROM_TEMPLATE, true) }
|
||||
}
|
||||
}
|
||||
+5
-20
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.TemplateKind
|
||||
import org.jetbrains.kotlin.idea.core.getFunctionBodyTextFromTemplate
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.BodyType.*
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.BodyType.*
|
||||
import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.j2k.IdeaDocCommentConverter
|
||||
import org.jetbrains.kotlin.idea.kdoc.KDocElementFactory
|
||||
@@ -40,15 +40,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.setSingleOverridden
|
||||
import org.jetbrains.kotlin.util.findCallableMemberBySignature
|
||||
|
||||
interface OverrideMemberChooserObject : ClassMember {
|
||||
sealed class BodyType(val requiresReturn: Boolean = true) {
|
||||
object NO_BODY : BodyType()
|
||||
object EMPTY_OR_TEMPLATE : BodyType(requiresReturn = false)
|
||||
object FROM_TEMPLATE : BodyType(requiresReturn = false)
|
||||
object SUPER : BodyType()
|
||||
object QUALIFIED_SUPER : BodyType()
|
||||
|
||||
class Delegate(val receiverName: String) : BodyType()
|
||||
}
|
||||
|
||||
val descriptor: CallableMemberDescriptor
|
||||
val immediateSuper: CallableMemberDescriptor
|
||||
@@ -111,12 +102,6 @@ interface OverrideMemberChooserObject : ClassMember {
|
||||
}
|
||||
}
|
||||
|
||||
enum class MemberGenerateMode {
|
||||
OVERRIDE,
|
||||
ACTUAL,
|
||||
EXPECT
|
||||
}
|
||||
|
||||
fun OverrideMemberChooserObject.generateMember(
|
||||
targetClass: KtClassOrObject,
|
||||
copyDoc: Boolean
|
||||
@@ -271,7 +256,7 @@ private fun generateProperty(
|
||||
project: Project,
|
||||
descriptor: PropertyDescriptor,
|
||||
renderer: DescriptorRenderer,
|
||||
bodyType: OverrideMemberChooserObject.BodyType,
|
||||
bodyType: BodyType,
|
||||
forceOverride: Boolean
|
||||
): KtProperty {
|
||||
val newDescriptor = descriptor.wrap(forceOverride)
|
||||
@@ -308,7 +293,7 @@ private fun generateFunction(
|
||||
project: Project,
|
||||
descriptor: FunctionDescriptor,
|
||||
renderer: DescriptorRenderer,
|
||||
bodyType: OverrideMemberChooserObject.BodyType,
|
||||
bodyType: BodyType,
|
||||
forceOverride: Boolean
|
||||
): KtFunction {
|
||||
val newDescriptor = descriptor.wrap(forceOverride)
|
||||
@@ -336,13 +321,13 @@ private fun generateFunction(
|
||||
}
|
||||
}
|
||||
|
||||
private fun OverrideMemberChooserObject.BodyType.effectiveBodyType(canBeEmpty: Boolean): OverrideMemberChooserObject.BodyType =
|
||||
private fun BodyType.effectiveBodyType(canBeEmpty: Boolean): BodyType =
|
||||
if (!canBeEmpty && this == EMPTY_OR_TEMPLATE) FROM_TEMPLATE else this
|
||||
|
||||
fun generateUnsupportedOrSuperCall(
|
||||
project: Project,
|
||||
descriptor: CallableMemberDescriptor,
|
||||
bodyType: OverrideMemberChooserObject.BodyType,
|
||||
bodyType: BodyType,
|
||||
canBeEmpty: Boolean = true
|
||||
): String {
|
||||
when (bodyType.effectiveBodyType(canBeEmpty)) {
|
||||
|
||||
+5
-5
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import java.util.*
|
||||
|
||||
class OverrideMembersHandler(private val preferConstructorParameters: Boolean = false) : OverrideImplementMembersHandler() {
|
||||
class OverrideMembersHandler(private val preferConstructorParameters: Boolean = false) : GenerateMembersHandler() {
|
||||
override fun collectMembersToGenerate(descriptor: ClassDescriptor, project: Project): Collection<OverrideMemberChooserObject> {
|
||||
val result = ArrayList<OverrideMemberChooserObject>()
|
||||
for (member in descriptor.unsubstitutedMemberScope.getContributedDescriptors()) {
|
||||
@@ -56,13 +56,13 @@ class OverrideMembersHandler(private val preferConstructorParameters: Boolean =
|
||||
|
||||
val bodyType = when {
|
||||
descriptor.kind == ClassKind.INTERFACE && realSuper.builtIns.isMemberOfAny(realSuper) ->
|
||||
OverrideMemberChooserObject.BodyType.NO_BODY
|
||||
BodyType.NO_BODY
|
||||
immediateSuperToUse.modality == Modality.ABSTRACT ->
|
||||
OverrideMemberChooserObject.BodyType.FROM_TEMPLATE
|
||||
BodyType.FROM_TEMPLATE
|
||||
realSupersToUse.size == 1 ->
|
||||
OverrideMemberChooserObject.BodyType.SUPER
|
||||
BodyType.SUPER
|
||||
else ->
|
||||
OverrideMemberChooserObject.BodyType.QUALIFIED_SUPER
|
||||
BodyType.QUALIFIED_SUPER
|
||||
}
|
||||
|
||||
result.add(
|
||||
|
||||
+39
-62
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -9,17 +9,14 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.editor.ScrollType
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.allChildren
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.utils.ifEmpty
|
||||
import kotlin.math.min
|
||||
|
||||
fun moveCaretIntoGeneratedElement(editor: Editor, element: PsiElement) {
|
||||
@@ -200,75 +197,55 @@ private fun removeAfterOffset(offset: Int, whiteSpace: PsiWhiteSpace): PsiElemen
|
||||
return whiteSpace
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun <T : KtDeclaration> insertMembersAfter(
|
||||
editor: Editor?,
|
||||
classOrObject: KtClassOrObject,
|
||||
members: Collection<T>,
|
||||
anchor: PsiElement? = null,
|
||||
getAnchor: (KtDeclaration) -> PsiElement? = { null }
|
||||
): List<T> {
|
||||
getAnchor: (KtDeclaration) -> PsiElement? = { null },
|
||||
): List<SmartPsiElementPointer<T>> {
|
||||
members.ifEmpty { return emptyList() }
|
||||
val project = classOrObject.project
|
||||
return runWriteAction {
|
||||
val insertedMembers = SmartList<SmartPsiElementPointer<T>>()
|
||||
fun insertedMembersElements() = insertedMembers.mapNotNull { it.element }
|
||||
val insertedMembers = SmartList<SmartPsiElementPointer<T>>()
|
||||
val (parameters, otherMembers) = members.partition { it is KtParameter }
|
||||
|
||||
val (parameters, otherMembers) = members.partition { it is KtParameter }
|
||||
parameters.mapNotNullTo(insertedMembers) {
|
||||
if (classOrObject !is KtClass) return@mapNotNullTo null
|
||||
|
||||
parameters.mapNotNullTo(insertedMembers) {
|
||||
if (classOrObject !is KtClass) return@mapNotNullTo null
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
SmartPointerManager.createPointer(
|
||||
classOrObject.createPrimaryConstructorParameterListIfAbsent().addParameter(it as KtParameter) as T
|
||||
)
|
||||
}
|
||||
|
||||
if (otherMembers.isNotEmpty()) {
|
||||
val body = classOrObject.getOrCreateBody()
|
||||
|
||||
var afterAnchor = anchor ?: findInsertAfterAnchor(editor, body) ?: return emptyList()
|
||||
otherMembers.mapTo(insertedMembers) {
|
||||
afterAnchor = getAnchor(it) ?: afterAnchor
|
||||
|
||||
if (classOrObject is KtClass && classOrObject.isEnum()) {
|
||||
val enumEntries = classOrObject.declarations.filterIsInstance<KtEnumEntry>()
|
||||
val bound = (enumEntries.lastOrNull() ?: classOrObject.allChildren.firstOrNull { element ->
|
||||
element.node.elementType == KtTokens.SEMICOLON
|
||||
})
|
||||
if (it !is KtEnumEntry) {
|
||||
if (bound != null && afterAnchor.startOffset <= bound.startOffset) {
|
||||
afterAnchor = bound
|
||||
}
|
||||
} else if (bound == null && body.declarations.isNotEmpty()) {
|
||||
afterAnchor = body.lBrace!!
|
||||
} else if (bound != null && afterAnchor.startOffset > bound.startOffset) {
|
||||
afterAnchor = bound.prevSibling!!
|
||||
}
|
||||
}
|
||||
|
||||
it.removeModifier(KtTokens.EXTERNAL_KEYWORD)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
SmartPointerManager.createPointer(
|
||||
classOrObject.createPrimaryConstructorParameterListIfAbsent().addParameter(it as KtParameter) as T
|
||||
)
|
||||
SmartPointerManager.createPointer((body.addAfter(it, afterAnchor) as T).apply { afterAnchor = this })
|
||||
}
|
||||
|
||||
if (otherMembers.isNotEmpty()) {
|
||||
val body = classOrObject.getOrCreateBody()
|
||||
|
||||
var afterAnchor = anchor ?: findInsertAfterAnchor(editor, body) ?: return@runWriteAction emptyList<T>()
|
||||
otherMembers.mapTo(insertedMembers) {
|
||||
afterAnchor = getAnchor(it) ?: afterAnchor
|
||||
|
||||
if (classOrObject is KtClass && classOrObject.isEnum()) {
|
||||
val enumEntries = classOrObject.declarations.filterIsInstance<KtEnumEntry>()
|
||||
val bound = (enumEntries.lastOrNull() ?: classOrObject.allChildren.firstOrNull { element ->
|
||||
element.node.elementType == KtTokens.SEMICOLON
|
||||
})
|
||||
if (it !is KtEnumEntry) {
|
||||
if (bound != null && afterAnchor.startOffset <= bound.startOffset) {
|
||||
afterAnchor = bound
|
||||
}
|
||||
} else if (bound == null && body.declarations.isNotEmpty()) {
|
||||
afterAnchor = body.lBrace!!
|
||||
} else if (bound != null && afterAnchor.startOffset > bound.startOffset) {
|
||||
afterAnchor = bound.prevSibling!!
|
||||
}
|
||||
}
|
||||
|
||||
it.removeModifier(KtTokens.EXTERNAL_KEYWORD)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
SmartPointerManager.createPointer((body.addAfter(it, afterAnchor) as T).apply { afterAnchor = this })
|
||||
}
|
||||
}
|
||||
|
||||
ShortenReferences.DEFAULT.process(insertedMembersElements())
|
||||
|
||||
val firstElement = insertedMembersElements().firstOrNull() ?: return@runWriteAction emptyList()
|
||||
if (editor != null) {
|
||||
moveCaretIntoGeneratedElement(editor, firstElement)
|
||||
}
|
||||
|
||||
val codeStyleManager = CodeStyleManager.getInstance(project)
|
||||
insertedMembersElements().forEach { codeStyleManager.reformat(it) }
|
||||
|
||||
insertedMembersElements().toList()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : KtDeclaration> insertMember(editor: Editor?, classOrObject: KtClassOrObject, declaration: T, anchor: PsiElement? = null): T {
|
||||
return insertMembersAfter(editor, classOrObject, listOf(declaration), anchor).single()
|
||||
return insertedMembers
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core.overrideImplement
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService
|
||||
import com.intellij.codeInsight.generation.ClassMember
|
||||
import com.intellij.codeInsight.hint.HintManager
|
||||
import com.intellij.ide.util.MemberChooser
|
||||
import com.intellij.lang.LanguageCodeInsightActionHandler
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.DialogWrapper
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
|
||||
abstract class AbstractGenerateMembersHandler<T : ClassMember> : LanguageCodeInsightActionHandler {
|
||||
|
||||
abstract fun collectMembersToGenerate(classOrObject: KtClassOrObject): Collection<T>
|
||||
|
||||
protected abstract fun getChooserTitle(): String
|
||||
|
||||
protected abstract fun getNoMembersFoundHint(): String
|
||||
|
||||
protected abstract fun generateMembers(
|
||||
editor: Editor,
|
||||
classOrObject: KtClassOrObject,
|
||||
selectedElements: Collection<T>,
|
||||
copyDoc: Boolean
|
||||
)
|
||||
|
||||
protected open fun isValidForClass(classOrObject: KtClassOrObject) = true
|
||||
|
||||
private fun showOverrideImplementChooser(
|
||||
project: Project,
|
||||
members: Collection<T>
|
||||
): MemberChooser<T>? {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val memberArray = members.toTypedArray<ClassMember>() as Array<T>
|
||||
val chooser = MemberChooser(memberArray, true, true, project)
|
||||
chooser.title = getChooserTitle()
|
||||
chooser.show()
|
||||
if (chooser.exitCode != DialogWrapper.OK_EXIT_CODE) return null
|
||||
return chooser
|
||||
}
|
||||
|
||||
override fun isValidFor(editor: Editor, file: PsiFile): Boolean {
|
||||
if (file !is KtFile) return false
|
||||
val elementAtCaret = file.findElementAt(editor.caretModel.offset)
|
||||
val classOrObject = elementAtCaret?.getNonStrictParentOfType<KtClassOrObject>()
|
||||
return classOrObject != null && isValidForClass(classOrObject)
|
||||
}
|
||||
|
||||
override fun invoke(project: Project, editor: Editor, file: PsiFile) {
|
||||
invoke(project, editor, file, implementAll = ApplicationManager.getApplication().isUnitTestMode)
|
||||
}
|
||||
|
||||
fun invoke(project: Project, editor: Editor, file: PsiFile, implementAll: Boolean) {
|
||||
val elementAtCaret = file.findElementAt(editor.caretModel.offset)
|
||||
val classOrObject = elementAtCaret?.getNonStrictParentOfType<KtClassOrObject>() ?: return
|
||||
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return
|
||||
|
||||
val members = collectMembersToGenerate(classOrObject)
|
||||
if (members.isEmpty() && !implementAll) {
|
||||
HintManager.getInstance().showErrorHint(editor, getNoMembersFoundHint())
|
||||
return
|
||||
}
|
||||
|
||||
val copyDoc: Boolean
|
||||
val selectedElements: Collection<T
|
||||
>
|
||||
if (implementAll) {
|
||||
selectedElements = members
|
||||
copyDoc = false
|
||||
} else {
|
||||
val chooser = showOverrideImplementChooser(project, members) ?: return
|
||||
selectedElements = chooser.selectedElements ?: return
|
||||
copyDoc = chooser.isCopyJavadoc
|
||||
}
|
||||
if (selectedElements.isEmpty()) return
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||
|
||||
generateMembers(editor, classOrObject, selectedElements, copyDoc)
|
||||
}
|
||||
|
||||
override fun startInWriteAction(): Boolean = false
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core.overrideImplement
|
||||
|
||||
sealed class BodyType(val requiresReturn: Boolean = true) {
|
||||
object NO_BODY : BodyType()
|
||||
object EMPTY_OR_TEMPLATE : BodyType(requiresReturn = false)
|
||||
object FROM_TEMPLATE : BodyType(requiresReturn = false)
|
||||
object SUPER : BodyType()
|
||||
object QUALIFIED_SUPER : BodyType()
|
||||
|
||||
class Delegate(val receiverName: String) : BodyType()
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.core.overrideImplement
|
||||
|
||||
enum class MemberGenerateMode {
|
||||
OVERRIDE,
|
||||
ACTUAL,
|
||||
EXPECT
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
+2
-2
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.CollectingNameValidator
|
||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.core.insertMembersAfter
|
||||
import org.jetbrains.kotlin.idea.core.insertMembersAfterAndReformat
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.project.platform
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
@@ -326,6 +326,6 @@ class KotlinGenerateEqualsAndHashcodeAction : KotlinGenerateMemberActionBase<Kot
|
||||
addIfNotNull(generateHashCode(project, info, targetClass))
|
||||
}
|
||||
val anchor = with(targetClass.declarations) { lastIsInstanceOrNull<KtNamedFunction>() ?: lastOrNull() }
|
||||
return insertMembersAfter(editor, targetClass, prototypes, anchor)
|
||||
return insertMembersAfterAndReformat(editor, targetClass, prototypes, anchor)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ class KotlinGenerateSecondaryConstructorAction : KotlinGenerateMemberActionBase<
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
insertMembersAfter(editor, targetClass, prototypes, findAnchor())
|
||||
insertMembersAfterAndReformat(editor, targetClass, prototypes, findAnchor())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.insertMember
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.BodyType
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.BodyType
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.generateUnsupportedOrSuperCall
|
||||
import org.jetbrains.kotlin.idea.j2k.j2k
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.setupEditorSelection
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.insertMembersAfter
|
||||
import org.jetbrains.kotlin.idea.core.insertMembersAfterAndReformat
|
||||
import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -202,6 +202,6 @@ class KotlinGenerateToStringAction : KotlinGenerateMemberActionBase<KotlinGenera
|
||||
val targetClass = info.classDescriptor.source.getPsi() as KtClass
|
||||
val prototype = generateToString(targetClass, info) ?: return emptyList()
|
||||
val anchor = with(targetClass.declarations) { lastIsInstanceOrNull<KtNamedFunction>() ?: lastOrNull() }
|
||||
return insertMembersAfter(editor, targetClass, listOf(prototype), anchor)
|
||||
return insertMembersAfterAndReformat(editor, targetClass, listOf(prototype), anchor)
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import com.intellij.openapi.ui.Messages
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.BodyType
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
@@ -70,6 +71,6 @@ fun confirmMemberRewrite(targetClass: KtClass, vararg descriptors: FunctionDescr
|
||||
|
||||
fun generateFunctionSkeleton(descriptor: FunctionDescriptor, targetClass: KtClassOrObject): KtNamedFunction {
|
||||
return OverrideMemberChooserObject
|
||||
.create(targetClass.project, descriptor, descriptor, OverrideMemberChooserObject.BodyType.FROM_TEMPLATE)
|
||||
.create(targetClass.project, descriptor, descriptor, BodyType.FROM_TEMPLATE)
|
||||
.generateMember(targetClass, false) as KtNamedFunction
|
||||
}
|
||||
@@ -30,7 +30,8 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaClassDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideImplementMembersHandler
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.BodyType
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.GenerateMembersHandler
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.core.util.runSynchronouslyWithProgress
|
||||
import org.jetbrains.kotlin.idea.refactoring.isAbstract
|
||||
@@ -120,10 +121,10 @@ abstract class ImplementAbstractMemberIntentionBase : SelfTargetingRangeIntentio
|
||||
member.project,
|
||||
descriptorToImplement,
|
||||
descriptorToImplement,
|
||||
OverrideMemberChooserObject.BodyType.FROM_TEMPLATE,
|
||||
BodyType.FROM_TEMPLATE,
|
||||
preferConstructorParameters
|
||||
)
|
||||
OverrideImplementMembersHandler.generateMembers(editor, targetClass, listOf(chooserObject), false)
|
||||
GenerateMembersHandler.generateMembers(editor, targetClass, listOf(chooserObject), false)
|
||||
}
|
||||
|
||||
private fun implementInJavaClass(member: KtNamedDeclaration, targetClass: PsiClass) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideImplementMembersHandler
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.GenerateMembersHandler
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -60,7 +60,7 @@ class MakePrivateAndOverrideMemberFix(
|
||||
if (makePrivate) {
|
||||
element.addModifier(KtTokens.PRIVATE_KEYWORD)
|
||||
}
|
||||
OverrideImplementMembersHandler.generateMembers(editor, containingClassOrObject, listOf(memberToOverride), false)
|
||||
GenerateMembersHandler.generateMembers(editor, containingClassOrObject, listOf(memberToOverride), false)
|
||||
}
|
||||
|
||||
object AccidentalOverrideFactory : KotlinSingleIntentionActionFactory() {
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent
|
||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.BodyType
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -72,7 +73,7 @@ class SpecifyOverrideExplicitlyFix(
|
||||
|
||||
val overrideMemberChooserObject = OverrideMemberChooserObject.create(
|
||||
project, delegatedDescriptor, overriddenDescriptor,
|
||||
OverrideMemberChooserObject.BodyType.Delegate(delegateTargetDescriptor.name.asString())
|
||||
BodyType.Delegate(delegateTargetDescriptor.name.asString())
|
||||
)
|
||||
val member = overrideMemberChooserObject.generateMember(element, copyDoc = false)
|
||||
val insertedMember = element.addDeclaration(member)
|
||||
|
||||
@@ -20,8 +20,8 @@ import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.core.findOrCreateDirectoryForPackage
|
||||
import org.jetbrains.kotlin.idea.core.getFqNameWithImplicitPrefix
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.MemberGenerateMode
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.BodyType.EMPTY_OR_TEMPLATE
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.BodyType.NO_BODY
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.BodyType.EMPTY_OR_TEMPLATE
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.BodyType.NO_BODY
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject.Companion.create
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.makeNotActual
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.ImplementMembersHandler
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideImplementMembersHandler
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.GenerateMembersHandler
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMembersHandler
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
@@ -88,33 +88,33 @@ abstract class AbstractOverrideImplementTest : KotlinLightCodeInsightFixtureTest
|
||||
myFixture.checkResultByFile(getTestName(true) + "/foo/JavaClass.java.after")
|
||||
}
|
||||
|
||||
private fun doFileTest(handler: OverrideImplementMembersHandler, memberToOverride: String? = null) {
|
||||
private fun doFileTest(handler: GenerateMembersHandler, memberToOverride: String? = null) {
|
||||
myFixture.configureByFile(getTestName(true) + ".kt")
|
||||
doOverrideImplement(handler, memberToOverride)
|
||||
checkResultByFile(getTestName(true) + ".kt.after")
|
||||
}
|
||||
|
||||
private fun doMultiFileTest(handler: OverrideImplementMembersHandler) {
|
||||
private fun doMultiFileTest(handler: GenerateMembersHandler) {
|
||||
myFixture.configureByFile(getTestName(true) + ".kt")
|
||||
doMultiOverrideImplement(handler)
|
||||
checkResultByFile(getTestName(true) + ".kt.after")
|
||||
}
|
||||
|
||||
private fun doDirectoryTest(handler: OverrideImplementMembersHandler, memberToOverride: String? = null) {
|
||||
private fun doDirectoryTest(handler: GenerateMembersHandler, memberToOverride: String? = null) {
|
||||
myFixture.copyDirectoryToProject(getTestName(true), "")
|
||||
myFixture.configureFromTempProjectFile("foo/Impl.kt")
|
||||
doOverrideImplement(handler, memberToOverride)
|
||||
checkResultByFile(getTestName(true) + "/foo/Impl.kt.after")
|
||||
}
|
||||
|
||||
private fun doMultiDirectoryTest(handler: OverrideImplementMembersHandler) {
|
||||
private fun doMultiDirectoryTest(handler: GenerateMembersHandler) {
|
||||
myFixture.copyDirectoryToProject(getTestName(true), "")
|
||||
myFixture.configureFromTempProjectFile("foo/Impl.kt")
|
||||
doMultiOverrideImplement(handler)
|
||||
checkResultByFile(getTestName(true) + "/foo/Impl.kt.after")
|
||||
}
|
||||
|
||||
private fun doOverrideImplement(handler: OverrideImplementMembersHandler, memberToOverride: String?) {
|
||||
private fun doOverrideImplement(handler: GenerateMembersHandler, memberToOverride: String?) {
|
||||
val elementAtCaret = myFixture.file.findElementAt(myFixture.editor.caretModel.offset)
|
||||
val classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, KtClassOrObject::class.java)
|
||||
?: error("Caret should be inside class or object")
|
||||
@@ -138,7 +138,7 @@ abstract class AbstractOverrideImplementTest : KotlinLightCodeInsightFixtureTest
|
||||
performGenerateCommand(classOrObject, listOf(singleToOverride))
|
||||
}
|
||||
|
||||
private fun doMultiOverrideImplement(handler: OverrideImplementMembersHandler) {
|
||||
private fun doMultiOverrideImplement(handler: GenerateMembersHandler) {
|
||||
val elementAtCaret = myFixture.file.findElementAt(myFixture.editor.caretModel.offset)
|
||||
val classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, KtClassOrObject::class.java)
|
||||
?: error("Caret should be inside class or object")
|
||||
@@ -167,7 +167,7 @@ abstract class AbstractOverrideImplementTest : KotlinLightCodeInsightFixtureTest
|
||||
try {
|
||||
val copyDoc = InTextDirectivesUtils.isDirectiveDefined(classOrObject.containingFile.text, "// COPY_DOC")
|
||||
myFixture.project.executeWriteCommand("") {
|
||||
OverrideImplementMembersHandler.generateMembers(myFixture.editor, classOrObject, selectedElements, copyDoc)
|
||||
GenerateMembersHandler.generateMembers(myFixture.editor, classOrObject, selectedElements, copyDoc)
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
throw rethrow(throwable)
|
||||
|
||||
Reference in New Issue
Block a user