diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt index 5308411f8bf..4a3fe857fbc 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/createClass/CreateClassFromUsageFix.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass import com.intellij.codeInsight.intention.HighPriorityAction import com.intellij.codeInsight.intention.LowPriorityAction -import com.intellij.codeInsight.intention.impl.CreateClassDialog import com.intellij.ide.util.DirectoryChooserUtil import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.editor.Editor @@ -70,14 +69,14 @@ val ClassKind.actionPriority: IntentionActionPriority get() = if (this == ANNOTATION_CLASS) IntentionActionPriority.LOW else IntentionActionPriority.NORMAL data class ClassInfo( - val kind: ClassKind = ClassKind.DEFAULT, - val name: String, - private val targetParents: List, - val expectedTypeInfo: TypeInfo, - val inner: Boolean = false, - val open: Boolean = false, - val typeArguments: List = Collections.emptyList(), - val parameterInfos: List = Collections.emptyList() + val kind: ClassKind = ClassKind.DEFAULT, + val name: String, + private val targetParents: List, + val expectedTypeInfo: TypeInfo, + val inner: Boolean = false, + val open: Boolean = false, + val typeArguments: List = Collections.emptyList(), + val parameterInfos: List = Collections.emptyList() ) { val applicableParents by lazy { targetParents.filter { @@ -87,10 +86,10 @@ data class ClassInfo( } } -open class CreateClassFromUsageFix protected constructor ( - element: E, - private val classInfo: ClassInfo -): CreateFromUsageFixBase(element) { +open class CreateClassFromUsageFix protected constructor( + element: E, + private val classInfo: ClassInfo +) : CreateFromUsageFixBase(element) { override fun getText() = "Create ${classInfo.kind.description} '${classInfo.name}'" override fun isAvailable(project: Project, editor: Editor?, file: KtFile): Boolean { @@ -114,11 +113,11 @@ open class CreateClassFromUsageFix protected constructor ( if (editor == null) return val applicableParents = SmartList().also { parents -> - classInfo.applicableParents.filterNotTo(parents) { - it is KtClassOrObject && it.superTypeListEntries.any { + classInfo.applicableParents.filterNotTo(parents) { element -> + element is KtClassOrObject && element.superTypeListEntries.any { when (it) { - is KtDelegatedSuperTypeEntry, is KtSuperTypeEntry -> it.typeAsUserType == element - is KtSuperTypeCallEntry -> it == element + is KtDelegatedSuperTypeEntry, is KtSuperTypeEntry -> it.typeAsUserType == this.element + is KtSuperTypeCallEntry -> it == this.element else -> false } } @@ -129,8 +128,8 @@ open class CreateClassFromUsageFix protected constructor ( } if (ApplicationManager.getApplication().isUnitTestMode) { - val targetParent = applicableParents.firstOrNull { - it.allChildren.any { it is PsiComment && it.text == "// TARGET_PARENT:" } + val targetParent = applicableParents.firstOrNull { element -> + element.allChildren.any { it is PsiComment && it.text == "// TARGET_PARENT:" } } ?: classInfo.applicableParents.last() return doInvoke(targetParent, editor, file) } @@ -141,22 +140,21 @@ open class CreateClassFromUsageFix protected constructor ( } private fun createFileByPackage( - psiPackage: PsiPackage, - editor: Editor, - originalFile: KtFile + psiPackage: PsiPackage, + editor: Editor, + originalFile: KtFile ): KtFile? { val directories = psiPackage.directories.filter { it.canRefactor() } - assert (directories.isNotEmpty()) { "Package '${psiPackage.qualifiedName}' must be refactorable" } + assert(directories.isNotEmpty()) { "Package '${psiPackage.qualifiedName}' must be refactorable" } val currentModule = ModuleUtilCore.findModuleForPsiElement(originalFile) val preferredDirectory = - directories.firstOrNull { ModuleUtilCore.findModuleForPsiElement(it) == currentModule } + directories.firstOrNull { ModuleUtilCore.findModuleForPsiElement(it) == currentModule } ?: directories.firstOrNull() val targetDirectory = if (directories.size > 1 && !ApplicationManager.getApplication().isUnitTestMode) { DirectoryChooserUtil.chooseDirectory(directories.toTypedArray(), preferredDirectory, originalFile.project, HashMap()) - } - else { + } else { preferredDirectory } ?: return null @@ -165,11 +163,11 @@ open class CreateClassFromUsageFix protected constructor ( if (targetFile == null) { val filePath = "${targetDirectory.virtualFile.path}/$fileName" CodeInsightUtils.showErrorHint( - targetDirectory.project, - editor, - "File $filePath already exists but does not correspond to Kotlin file", - "Create file", - null + targetDirectory.project, + editor, + "File $filePath already exists but does not correspond to Kotlin file", + "Create file", + null ) } return targetFile @@ -186,13 +184,13 @@ open class CreateClassFromUsageFix protected constructor ( val ideaClassKind = classInfo.kind.toIdeaClassKind() val defaultPackageFqName = file.packageFqName val dialog = object : CreateKotlinClassDialog( - file.project, - "Create ${ideaClassKind.description.capitalize()}", - className, - defaultPackageFqName.asString(), - ideaClassKind, - false, - file.module + file.project, + "Create ${ideaClassKind.description.capitalize()}", + className, + defaultPackageFqName.asString(), + ideaClassKind, + false, + file.module ) { override fun reportBaseInSourceSelectionInTest() = true } @@ -217,19 +215,19 @@ open class CreateClassFromUsageFix protected constructor ( runWriteAction { with(classInfo) { val targetParent = - when (selectedParent) { - is KtElement, is PsiClass -> selectedParent - is PsiPackage -> createFileByPackage(selectedParent, editor, file) - else -> throw AssertionError("Unexpected element: " + selectedParent.text) - } ?: return@runWriteAction + when (selectedParent) { + is KtElement, is PsiClass -> selectedParent + is PsiPackage -> createFileByPackage(selectedParent, editor, file) + else -> throw AssertionError("Unexpected element: " + selectedParent.text) + } ?: return@runWriteAction val constructorInfo = ClassWithPrimaryConstructorInfo(classInfo, expectedTypeInfo) val builder = CallableBuilderConfiguration( - Collections.singletonList(constructorInfo), - element, - file, - editor, - false, - kind == PLAIN_CLASS || kind == INTERFACE + Collections.singletonList(constructorInfo), + element, + file, + editor, + false, + kind == PLAIN_CLASS || kind == INTERFACE ).createBuilder() builder.placement = CallablePlacement.NoReceiver(targetParent) @@ -240,16 +238,15 @@ open class CreateClassFromUsageFix protected constructor ( if (targetPackageFqName == file.packageFqName) return@build val reference = (element.getQualifiedElementSelector() as? KtSimpleNameExpression)?.mainReference ?: return@build reference.bindToFqName( - targetPackageFqName.child(Name.identifier(className)), - KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING + targetPackageFqName.child(Name.identifier(className)), + KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING ) } } if (startCommand) { file.project.executeCommand(text, command = ::buildClass) - } - else { + } else { buildClass() } } @@ -257,13 +254,13 @@ open class CreateClassFromUsageFix protected constructor ( } private class LowPriorityCreateClassFromUsageFix( - element: E, - classInfo: ClassInfo + element: E, + classInfo: ClassInfo ) : CreateClassFromUsageFix(element, classInfo), LowPriorityAction private class HighPriorityCreateClassFromUsageFix( - element: E, - classInfo: ClassInfo + element: E, + classInfo: ClassInfo ) : CreateClassFromUsageFix(element, classInfo), HighPriorityAction companion object { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt index eb5542e33c9..56cd7648c95 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt @@ -379,14 +379,13 @@ fun chooseContainerElement( editor, containers, object : PsiElementListCellRenderer() { - private fun PsiElement.renderName(): String { - if (this is KtPropertyAccessor) { - return property.renderName() + if (isGetter) ".get" else ".set" + private fun PsiElement.renderName(): String = when { + this is KtPropertyAccessor -> property.renderName() + if (isGetter) ".get" else ".set" + this is KtObjectDeclaration && isCompanion() -> { + val name = getStrictParentOfType()?.renderName() ?: "" + "Companion object of $name" } - if (this is KtObjectDeclaration && this.isCompanion()) { - return "Companion object of ${getStrictParentOfType()?.renderName() ?: ""}" - } - return (this as? PsiNamedElement)?.name ?: "" + else -> (this as? PsiNamedElement)?.name ?: "" } private fun PsiElement.renderDeclaration(): String? { @@ -399,9 +398,11 @@ fun chooseContainerElement( else -> null } ?: return null val name = renderName() - val params = (descriptor as? FunctionDescriptor)?.valueParameters - ?.map { DescriptorRenderer.Companion.SHORT_NAMES_IN_TYPES.renderType(it.type) } - ?.joinToString(", ", "(", ")") ?: "" + val params = (descriptor as? FunctionDescriptor)?.valueParameters?.joinToString( + ", ", + "(", + ")" + ) { DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(it.type) } ?: "" return "$name$params" } @@ -410,12 +411,10 @@ fun chooseContainerElement( return StringUtil.shortenTextWithEllipsis(text!!.collapseSpaces(), 53, 0) } - private fun PsiElement.getRepresentativeElement(): PsiElement { - return when (this) { - is KtBlockExpression -> (parent as? KtDeclarationWithBody) ?: this - is KtClassBody -> parent as KtClassOrObject - else -> this - } + private fun PsiElement.getRepresentativeElement(): PsiElement = when (this) { + is KtBlockExpression -> (parent as? KtDeclarationWithBody) ?: this + is KtClassBody -> parent as KtClassOrObject + else -> this } override fun getElementText(element: PsiElement): String? { @@ -457,19 +456,14 @@ fun chooseContainerElementIfNecessary( fun PsiElement.isTrueJavaMethod(): Boolean = this is PsiMethod && this !is KtLightMethod -fun PsiElement.canRefactor(): Boolean { - if (!this.isValid) return false - - return when { - this is PsiPackage -> - directories.any { it.canRefactor() } - this is KtElement || - this is PsiMember && language == JavaLanguage.INSTANCE || - this is PsiDirectory -> - ProjectRootsUtil.isInProjectSource(this, includeScriptsOutsideSourceRoots = true) - else -> - false - } +fun PsiElement.canRefactor(): Boolean = when { + !isValid -> false + this is PsiPackage -> directories.any { it.canRefactor() } + this is KtElement || this is PsiMember && language == JavaLanguage.INSTANCE || this is PsiDirectory -> ProjectRootsUtil.isInProjectSource( + this, + includeScriptsOutsideSourceRoots = true + ) + else -> false } private fun copyModifierListItems(from: PsiModifierList, to: PsiModifierList, withPsiModifiers: Boolean = true) { @@ -645,7 +639,7 @@ fun PsiElement.j2kText(): String? { val j2kConverter = JavaToKotlinConverter( project, - ConverterSettings.Companion.defaultSettings, + ConverterSettings.defaultSettings, IdeaJavaToKotlinServices ) return j2kConverter.elementsToKotlin(listOf(this)).results.single()?.text ?: return null //TODO: insert imports @@ -750,14 +744,12 @@ fun PsiNamedElement.isInterfaceClass(): Boolean = when (this) { else -> false } -fun KtNamedDeclaration.isAbstract(): Boolean { - if (hasModifier(KtTokens.ABSTRACT_KEYWORD)) return true - if (containingClassOrObject?.isInterfaceClass() != true) return false - return when (this) { - is KtProperty -> initializer == null && delegate == null && accessors.isEmpty() - is KtNamedFunction -> !hasBody() - else -> false - } +fun KtNamedDeclaration.isAbstract(): Boolean = when { + hasModifier(KtTokens.ABSTRACT_KEYWORD) -> true + containingClassOrObject?.isInterfaceClass() != true -> false + this is KtProperty -> initializer == null && delegate == null && accessors.isEmpty() + this is KtNamedFunction -> !hasBody() + else -> false } fun KtNamedDeclaration.isConstructorDeclaredProperty() = this is KtParameter && ownerFunction is KtPrimaryConstructor && hasValOrVar()