KT-9839: intention introduced: convert primary constructor to secondary one
(cherry picked from commit 93aaa48)
This commit is contained in:
committed by
Mikhail Glukhikh
parent
d4418d5686
commit
7f50e6e70e
@@ -1372,6 +1372,11 @@
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.intentions.ConvertPrimaryConstructorToSecondaryIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<localInspection implementationClass="org.jetbrains.kotlin.idea.intentions.ObjectLiteralToLambdaInspection"
|
||||
displayName="Object literal can be converted to lambda"
|
||||
groupName="Kotlin"
|
||||
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.lexer.KtTokens.THIS_KEYWORD
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.VARARG_KEYWORD
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory.CallableBuilder
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory.CallableBuilder.Target.CONSTRUCTOR
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
|
||||
class ConvertPrimaryConstructorToSecondaryIntention : SelfTargetingIntention<KtPrimaryConstructor>(
|
||||
KtPrimaryConstructor::class.java,
|
||||
"Convert to secondary constructor"
|
||||
) {
|
||||
override fun isApplicableTo(element: KtPrimaryConstructor, caretOffset: Int) =
|
||||
element.containingClassOrObject is KtClass && element.valueParameters.all { !it.hasValOrVar() || it.annotationEntries.isEmpty() }
|
||||
|
||||
override fun applyTo(element: KtPrimaryConstructor, editor: Editor?) {
|
||||
val klass = element.containingClassOrObject as? KtClass ?: return
|
||||
val factory = KtPsiFactory(klass)
|
||||
val initializerMap = mutableMapOf<KtProperty, String>()
|
||||
for (property in klass.getProperties()) {
|
||||
if (property.typeReference == null) {
|
||||
SpecifyTypeExplicitlyIntention().applyTo(property, editor)
|
||||
}
|
||||
val initializer = property.initializer ?: continue
|
||||
initializerMap[property] = initializer.text
|
||||
initializer.delete()
|
||||
property.equalsToken!!.delete()
|
||||
}
|
||||
val constructor = factory.createSecondaryConstructor(
|
||||
CallableBuilder(CONSTRUCTOR).apply {
|
||||
element.modifierList?.let { modifier(it.text) }
|
||||
typeParams()
|
||||
name()
|
||||
for (valueParameter in element.valueParameters) {
|
||||
val annotations = valueParameter.annotationEntries.joinToString(separator = " ") { it.text }
|
||||
val vararg = if (valueParameter.isVarArg) VARARG_KEYWORD.value else ""
|
||||
param("$annotations $vararg ${valueParameter.name!!}",
|
||||
valueParameter.typeReference!!.text, valueParameter.defaultValue?.text)
|
||||
}
|
||||
noReturnType()
|
||||
for (superTypeEntry in klass.getSuperTypeListEntries()) {
|
||||
if (superTypeEntry is KtSuperTypeCallEntry) {
|
||||
superDelegation(superTypeEntry.valueArgumentList?.text ?: "")
|
||||
superTypeEntry.replace(factory.createSuperTypeEntry(superTypeEntry.typeReference!!.text))
|
||||
}
|
||||
}
|
||||
if (element.valueParameters.firstOrNull { it.hasValOrVar() } != null || initializerMap.isNotEmpty()) {
|
||||
val valueParameterInitializers = element.valueParameters.filter { it.hasValOrVar() }.joinToString(separator = "\n") {
|
||||
val name = it.name!!
|
||||
"this.$name = $name"
|
||||
}
|
||||
val classBodyInitializers = klass.declarations.filter {
|
||||
(it is KtProperty && initializerMap[it] != null) || it is KtAnonymousInitializer
|
||||
}.joinToString(separator = "\n") {
|
||||
if (it is KtProperty) {
|
||||
val name = it.name!!
|
||||
val text = initializerMap[it]
|
||||
if (text != null) {
|
||||
"${THIS_KEYWORD.value}.$name = $text"
|
||||
}
|
||||
else {
|
||||
""
|
||||
}
|
||||
}
|
||||
else {
|
||||
((it as KtAnonymousInitializer).body as? KtBlockExpression)?.statements?.joinToString(separator = "\n") {
|
||||
it.text
|
||||
} ?: ""
|
||||
}
|
||||
}
|
||||
blockBody(listOf(valueParameterInitializers, classBodyInitializers)
|
||||
.filter(String::isNotEmpty).joinToString(separator = "\n"))
|
||||
}
|
||||
}.asString()
|
||||
)
|
||||
klass.addDeclarationBefore(constructor, null)
|
||||
for (valueParameter in element.valueParameters.reversed()) {
|
||||
if (!valueParameter.hasValOrVar()) continue
|
||||
val isVararg = valueParameter.hasModifier(VARARG_KEYWORD)
|
||||
valueParameter.removeModifier(VARARG_KEYWORD)
|
||||
val typeText = valueParameter.typeReference?.text
|
||||
val property = factory.createProperty(valueParameter.modifierList?.text, valueParameter.name!!,
|
||||
if (isVararg && typeText != null) "Array<out $typeText>" else typeText,
|
||||
valueParameter.isMutable, null)
|
||||
klass.addDeclarationBefore(property, null)
|
||||
}
|
||||
for (anonymousInitializer in klass.getAnonymousInitializers()) {
|
||||
anonymousInitializer.delete()
|
||||
}
|
||||
element.delete()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user