Not holding descriptor in SuperClassNotInitialized.AddParametersFix

This commit is contained in:
Valentin Kipyatkov
2015-10-15 13:44:57 +03:00
parent 412f4a30c4
commit 714e97751d
@@ -22,7 +22,6 @@ import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
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.psiUtil.endOffset
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.renderer.render
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.types.IndexedParametersSubstitution
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
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 parameterString = typesRendered.joinToString(", ", "(", if (types.size() <= maxParamsToDisplay) ")" else ",...)")
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(
element: JetDelegatorToSuperClass,
val classDeclaration: JetClass,
val superConstructor: ConstructorDescriptor, //TODO: do not hold descriptor!
private val classDeclaration: JetClass,
private val parametersToAdd: Collection<JetParameter>,
private val argumentText: String,
private val text: String
) : 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 {
return super.isAvailable(project, editor, file) && superConstructor.getValueParameters().none { it.getType().isError() }
if (superParameters.any { it.type.isError }) return null
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) {
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 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) {
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)
ShortenReferences.DEFAULT.process(typeRefsToShorten)