Not holding descriptor in SuperClassNotInitialized.AddParametersFix
This commit is contained in:
@@ -22,7 +22,6 @@ import com.intellij.codeInsight.intention.IntentionAction
|
|||||||
import com.intellij.openapi.application.ApplicationManager
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.editor.Editor
|
import com.intellij.openapi.editor.Editor
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.PsiFile
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
@@ -38,10 +37,12 @@ import org.jetbrains.kotlin.idea.util.ShortenReferences
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
|
import org.jetbrains.kotlin.renderer.render
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.types.IndexedParametersSubstitution
|
import org.jetbrains.kotlin.types.IndexedParametersSubstitution
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
public object SuperClassNotInitialized : JetIntentionActionsFactory() {
|
public object SuperClassNotInitialized : JetIntentionActionsFactory() {
|
||||||
@@ -92,7 +93,7 @@ public object SuperClassNotInitialized : JetIntentionActionsFactory() {
|
|||||||
val typesRendered = types.take(maxParamsToDisplay).map { DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(it) }
|
val typesRendered = types.take(maxParamsToDisplay).map { DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(it) }
|
||||||
val parameterString = typesRendered.joinToString(", ", "(", if (types.size() <= maxParamsToDisplay) ")" else ",...)")
|
val parameterString = typesRendered.joinToString(", ", "(", if (types.size() <= maxParamsToDisplay) ")" else ",...)")
|
||||||
val text = "Add constructor parameters from " + superClass.getName().asString() + parameterString
|
val text = "Add constructor parameters from " + superClass.getName().asString() + parameterString
|
||||||
fixes.add(AddParametersFix(delegator, classOrObjectDeclaration, constructor, text))
|
fixes.addIfNotNull(AddParametersFix.create(delegator, classOrObjectDeclaration, constructor, text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,56 +128,70 @@ public object SuperClassNotInitialized : JetIntentionActionsFactory() {
|
|||||||
|
|
||||||
private class AddParametersFix(
|
private class AddParametersFix(
|
||||||
element: JetDelegatorToSuperClass,
|
element: JetDelegatorToSuperClass,
|
||||||
val classDeclaration: JetClass,
|
private val classDeclaration: JetClass,
|
||||||
val superConstructor: ConstructorDescriptor, //TODO: do not hold descriptor!
|
private val parametersToAdd: Collection<JetParameter>,
|
||||||
|
private val argumentText: String,
|
||||||
private val text: String
|
private val text: String
|
||||||
) : KotlinQuickFixAction<JetDelegatorToSuperClass>(element) {
|
) : KotlinQuickFixAction<JetDelegatorToSuperClass>(element) {
|
||||||
|
|
||||||
override fun getFamilyName() = "Add constructor parameters from superclass"
|
companion object {
|
||||||
|
fun create(
|
||||||
|
element: JetDelegatorToSuperClass,
|
||||||
|
classDeclaration: JetClass,
|
||||||
|
superConstructor: ConstructorDescriptor,
|
||||||
|
text: String
|
||||||
|
): AddParametersFix? {
|
||||||
|
val superParameters = superConstructor.getValueParameters()
|
||||||
|
assert(superParameters.isNotEmpty())
|
||||||
|
|
||||||
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
if (superParameters.any { it.type.isError }) return null
|
||||||
return super.isAvailable(project, editor, file) && superConstructor.getValueParameters().none { it.getType().isError() }
|
|
||||||
|
val argumentText = StringBuilder()
|
||||||
|
val oldParameters = classDeclaration.getPrimaryConstructorParameters()
|
||||||
|
val parametersToAdd = ArrayList<JetParameter>()
|
||||||
|
for (parameter in superParameters) {
|
||||||
|
val nameRendered = parameter.name.render()
|
||||||
|
val varargElementType = parameter.varargElementType
|
||||||
|
|
||||||
|
if (argumentText.length > 0) {
|
||||||
|
argumentText.append(", ")
|
||||||
|
}
|
||||||
|
argumentText.append(if (varargElementType != null) "*$nameRendered" else nameRendered)
|
||||||
|
|
||||||
|
val nameString = parameter.getName().asString()
|
||||||
|
val existingParameter = oldParameters.firstOrNull { it.getName() == nameString }
|
||||||
|
if (existingParameter != null) {
|
||||||
|
val type = (existingParameter.resolveToDescriptor() as ValueParameterDescriptor).getType()
|
||||||
|
if (type.isSubtypeOf(parameter.getType())) continue // use existing parameter
|
||||||
|
}
|
||||||
|
|
||||||
|
val parameterText = if (varargElementType != null)
|
||||||
|
"vararg " + nameRendered + ":" + IdeDescriptorRenderers.SOURCE_CODE.renderType(varargElementType)
|
||||||
|
else
|
||||||
|
nameRendered + ":" + IdeDescriptorRenderers.SOURCE_CODE.renderType(parameter.type)
|
||||||
|
parametersToAdd.add(JetPsiFactory(element).createParameter(parameterText))
|
||||||
|
}
|
||||||
|
|
||||||
|
return AddParametersFix(element, classDeclaration, parametersToAdd, argumentText.toString(), text)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getText()= text
|
override fun getFamilyName() = "Add constructor parameters from superclass"
|
||||||
|
|
||||||
|
override fun getText() = text
|
||||||
|
|
||||||
override fun invoke(project: Project, editor: Editor?, file: JetFile) {
|
override fun invoke(project: Project, editor: Editor?, file: JetFile) {
|
||||||
val factory = JetPsiFactory(project)
|
val factory = JetPsiFactory(project)
|
||||||
val renderer = IdeDescriptorRenderers.SOURCE_CODE
|
|
||||||
|
|
||||||
val superParameters = superConstructor.getValueParameters()
|
|
||||||
assert(superParameters.isNotEmpty())
|
|
||||||
val parameterNames = ArrayList<String>()
|
|
||||||
val typeRefsToShorten = ArrayList<JetTypeReference>()
|
val typeRefsToShorten = ArrayList<JetTypeReference>()
|
||||||
val parameterList = classDeclaration.createPrimaryConstructorParameterListIfAbsent()
|
val parameterList = classDeclaration.createPrimaryConstructorParameterListIfAbsent()
|
||||||
val oldParameters = parameterList.getParameters()
|
|
||||||
val parametersToAdd = ArrayList<JetParameter>()
|
|
||||||
for (parameter in superParameters) {
|
|
||||||
val name = renderer.renderName(parameter.getName())
|
|
||||||
val varargElementType = parameter.getVarargElementType()
|
|
||||||
|
|
||||||
parameterNames.add(if (varargElementType != null) "*$name" else name)
|
|
||||||
|
|
||||||
val nameString = parameter.getName().asString()
|
|
||||||
val existingParameter = oldParameters.firstOrNull { it.getName() == nameString }
|
|
||||||
if (existingParameter != null) {
|
|
||||||
val type = (existingParameter.resolveToDescriptor() as ValueParameterDescriptor).getType()
|
|
||||||
if (type.isSubtypeOf(parameter.getType())) continue // use existing parameter
|
|
||||||
}
|
|
||||||
|
|
||||||
val parameterText = if (varargElementType != null)
|
|
||||||
"vararg " + name + ":" + renderer.renderType(varargElementType)
|
|
||||||
else
|
|
||||||
name + ":" + renderer.renderType(parameter.getType())
|
|
||||||
parametersToAdd.add(factory.createParameter(parameterText))
|
|
||||||
}
|
|
||||||
|
|
||||||
for (parameter in parametersToAdd) {
|
for (parameter in parametersToAdd) {
|
||||||
val newParameter = parameterList.addParameter(parameter)
|
val newParameter = parameterList.addParameter(parameter)
|
||||||
typeRefsToShorten.add(newParameter.getTypeReference()!!)
|
typeRefsToShorten.add(newParameter.typeReference!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
val delegatorCall = factory.createDelegatorToSuperCall(element.getText() + "(" + parameterNames.joinToString(",") + ")")
|
val delegatorCall = factory.createDelegatorToSuperCall(element.text + "(" + argumentText + ")")
|
||||||
element.replace(delegatorCall)
|
element.replace(delegatorCall)
|
||||||
|
|
||||||
ShortenReferences.DEFAULT.process(typeRefsToShorten)
|
ShortenReferences.DEFAULT.process(typeRefsToShorten)
|
||||||
|
|||||||
Reference in New Issue
Block a user