From eb918db3afe49850287536a6e255dd898395ee98 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Mon, 28 Mar 2016 19:06:38 +0300 Subject: [PATCH] Converting to Kotlin (step 2) --- .../idea/quickfix/ChangeVariableTypeFix.kt | 246 ++++++++---------- 1 file changed, 105 insertions(+), 141 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableTypeFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableTypeFix.kt index 2e4d3052678..f0be0590074 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableTypeFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeVariableTypeFix.kt @@ -14,170 +14,134 @@ * limitations under the License. */ -package org.jetbrains.kotlin.idea.quickfix; +package org.jetbrains.kotlin.idea.quickfix -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.descriptors.FunctionDescriptor; -import org.jetbrains.kotlin.descriptors.PropertyDescriptor; -import org.jetbrains.kotlin.diagnostics.Diagnostic; -import org.jetbrains.kotlin.idea.KotlinBundle; -import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils; -import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil; -import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers; -import org.jetbrains.kotlin.idea.util.ShortenReferences; -import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.psi.*; -import org.jetbrains.kotlin.resolve.BindingContext; -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; -import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; -import org.jetbrains.kotlin.types.ErrorUtils; -import org.jetbrains.kotlin.types.KotlinType; -import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiFile +import com.intellij.util.IncorrectOperationException +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor +import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil +import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers +import org.jetbrains.kotlin.idea.util.ShortenReferences +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.types.ErrorUtils +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.checker.KotlinTypeChecker +import java.util.* -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; +class ChangeVariableTypeFix(element: KtVariableDeclaration, private val type: KotlinType) : KotlinQuickFixAction(element) { -public class ChangeVariableTypeFix extends KotlinQuickFixAction { - private final KotlinType type; - - public ChangeVariableTypeFix(@NotNull KtVariableDeclaration element, @NotNull KotlinType type) { - super(element); - this.type = type; + override fun getText(): String { + var propertyName = element.fqName?.asString() ?: element.name + return KotlinBundle.message("change.element.type", propertyName, IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)) } - @NotNull - @Override - public String getText() { - String propertyName = getElement().getName(); - FqName fqName = getElement().getFqName(); - if (fqName != null) propertyName = fqName.asString(); - - return KotlinBundle - .message("change.element.type", propertyName, IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(type)); + override fun getFamilyName(): String { + return KotlinBundle.message("change.type.family") } - @NotNull - @Override - public String getFamilyName() { - return KotlinBundle.message("change.type.family"); + override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean { + return super.isAvailable(project, editor, file) && !ErrorUtils.containsErrorType(type) } - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiFile file) { - return super.isAvailable(project, editor, file) && !ErrorUtils.containsErrorType(type); - } + @Throws(IncorrectOperationException::class) + public override operator fun invoke(project: Project, editor: Editor?, file: KtFile) { + val psiFactory = KtPsiFactory(file) - @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull KtFile file) throws IncorrectOperationException { - KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(file); + val nameIdentifier = element.nameIdentifier ?: error("ChangeVariableTypeFix applied to variable without name") - PsiElement nameIdentifier = getElement().getNameIdentifier(); - assert nameIdentifier != null : "ChangeVariableTypeFix applied to variable without name"; + val replacingTypeReference = psiFactory.createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type)) + val toShorten = ArrayList() + toShorten.add(element.setTypeReference(replacingTypeReference)!!) - KtTypeReference replacingTypeReference = psiFactory.createType(IdeDescriptorRenderers.SOURCE_CODE.renderType(type)); - List toShorten = new ArrayList(); - toShorten.add(getElement().setTypeReference(replacingTypeReference)); - - if (getElement() instanceof KtProperty) { - KtPropertyAccessor getter = ((KtProperty) getElement()).getGetter(); - KtTypeReference getterReturnTypeRef = getter == null ? null : getter.getReturnTypeReference(); + if (element is KtProperty) { + val getter = element.getter + val getterReturnTypeRef = getter?.returnTypeReference if (getterReturnTypeRef != null) { - toShorten.add((KtTypeReference) getterReturnTypeRef.replace(replacingTypeReference)); + toShorten.add(getterReturnTypeRef.replace(replacingTypeReference) as KtTypeReference) } - KtPropertyAccessor setter = ((KtProperty) getElement()).getSetter(); - KtParameter setterParameter = setter == null ? null : setter.getParameter(); - KtTypeReference setterParameterTypeRef = setterParameter == null ? null : setterParameter.getTypeReference(); + val setter = element.setter + val setterParameter = setter?.parameter + val setterParameterTypeRef = setterParameter?.typeReference if (setterParameterTypeRef != null) { - toShorten.add((KtTypeReference) setterParameterTypeRef.replace(replacingTypeReference)); + toShorten.add(setterParameterTypeRef.replace(replacingTypeReference) as KtTypeReference) } } - ShortenReferences.DEFAULT.process(toShorten); + ShortenReferences.DEFAULT.process(toShorten) } - @NotNull - public static KotlinSingleIntentionActionFactory createFactoryForComponentFunctionReturnTypeMismatch() { - return new KotlinSingleIntentionActionFactory() { - @Nullable - @Override - public IntentionAction createAction(@NotNull Diagnostic diagnostic) { - KtDestructuringDeclarationEntry - entry = ChangeFunctionReturnTypeFix.getDestructuringDeclarationEntryThatTypeMismatchComponentFunction(diagnostic); - BindingContext context = ResolutionUtils.analyze(entry); - ResolvedCall resolvedCall = context.get(BindingContext.COMPONENT_RESOLVED_CALL, entry); - if (resolvedCall == null) return null; - KtFunction componentFunction = (KtFunction) DescriptorToSourceUtils - .descriptorToDeclaration(resolvedCall.getCandidateDescriptor()); - if (componentFunction == null) return null; - KotlinType expectedType = resolvedCall.getCandidateDescriptor().getReturnType(); - return expectedType == null ? null : new ChangeVariableTypeFix(entry, expectedType); - } - }; - } + companion object { - @NotNull - public static KotlinIntentionActionsFactory createFactoryForPropertyOrReturnTypeMismatchOnOverride() { - return new KotlinIntentionActionsFactory() { - @NotNull - @Override - protected List doCreateActions(@NotNull Diagnostic diagnostic) { - List actions = new LinkedList(); - - if (diagnostic.getPsiElement() instanceof KtProperty) { - KtProperty property = (KtProperty) diagnostic.getPsiElement(); - DeclarationDescriptor descriptor = ResolutionUtils.resolveToDescriptor(property); - if (!(descriptor instanceof PropertyDescriptor)) return actions; - PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; - - KotlinType - lowerBoundOfOverriddenPropertiesTypes = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(propertyDescriptor); - - KotlinType propertyType = propertyDescriptor.getReturnType(); - assert propertyType != null : "Property type cannot be null if it mismatch something"; - - List overriddenMismatchingProperties = new LinkedList(); - boolean canChangeOverriddenPropertyType = true; - for (PropertyDescriptor overriddenProperty: propertyDescriptor.getOverriddenDescriptors()) { - KotlinType overriddenPropertyType = overriddenProperty.getReturnType(); - if (overriddenPropertyType != null) { - if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(propertyType, overriddenPropertyType)) { - overriddenMismatchingProperties.add(overriddenProperty); - } - else if (overriddenProperty.isVar() && !KotlinTypeChecker.DEFAULT.equalTypes(overriddenPropertyType, propertyType)) { - canChangeOverriddenPropertyType = false; - } - if (overriddenProperty.isVar() && lowerBoundOfOverriddenPropertiesTypes != null && - !KotlinTypeChecker.DEFAULT.equalTypes(lowerBoundOfOverriddenPropertiesTypes, overriddenPropertyType)) { - lowerBoundOfOverriddenPropertiesTypes = null; - } - } - } - - if (lowerBoundOfOverriddenPropertiesTypes != null) { - actions.add(new ChangeVariableTypeFix(property, lowerBoundOfOverriddenPropertiesTypes)); - } - - if (overriddenMismatchingProperties.size() == 1 && canChangeOverriddenPropertyType) { - PsiElement overriddenProperty = DescriptorToSourceUtils - .descriptorToDeclaration(overriddenMismatchingProperties.get(0)); - if (overriddenProperty instanceof KtProperty) { - actions.add(new ChangeVariableTypeFix((KtProperty) overriddenProperty, propertyType)); - } - } + fun createFactoryForComponentFunctionReturnTypeMismatch(): KotlinSingleIntentionActionFactory { + return object : KotlinSingleIntentionActionFactory() { + public override fun createAction(diagnostic: Diagnostic): IntentionAction? { + val entry = ChangeFunctionReturnTypeFix.getDestructuringDeclarationEntryThatTypeMismatchComponentFunction(diagnostic) + val context = entry.analyze() + val resolvedCall = context.get(BindingContext.COMPONENT_RESOLVED_CALL, entry) ?: return null + val componentFunction = DescriptorToSourceUtils.descriptorToDeclaration(resolvedCall.candidateDescriptor) as KtFunction? ?: return null + val expectedType = resolvedCall.candidateDescriptor.returnType + return if (expectedType == null) null else ChangeVariableTypeFix(entry, expectedType) } - - return actions; } - }; + } + + fun createFactoryForPropertyOrReturnTypeMismatchOnOverride(): KotlinIntentionActionsFactory { + return object : KotlinIntentionActionsFactory() { + override fun doCreateActions(diagnostic: Diagnostic): List { + val actions = LinkedList() + + if (diagnostic.psiElement is KtProperty) { + val property = diagnostic.psiElement as KtProperty + val descriptor = property.resolveToDescriptor() + if (descriptor !is PropertyDescriptor) return actions + + var lowerBoundOfOverriddenPropertiesTypes = QuickFixUtil.findLowerBoundOfOverriddenCallablesReturnTypes(descriptor) + + val propertyType = descriptor.returnType ?: error("Property type cannot be null if it mismatch something") + + val overriddenMismatchingProperties = LinkedList() + var canChangeOverriddenPropertyType = true + for (overriddenProperty in descriptor.overriddenDescriptors) { + val overriddenPropertyType = overriddenProperty.returnType + if (overriddenPropertyType != null) { + if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(propertyType!!, overriddenPropertyType)) { + overriddenMismatchingProperties.add(overriddenProperty) + } + else if (overriddenProperty.isVar && !KotlinTypeChecker.DEFAULT.equalTypes(overriddenPropertyType, propertyType)) { + canChangeOverriddenPropertyType = false + } + if (overriddenProperty.isVar && lowerBoundOfOverriddenPropertiesTypes != null && + !KotlinTypeChecker.DEFAULT.equalTypes(lowerBoundOfOverriddenPropertiesTypes, overriddenPropertyType)) { + lowerBoundOfOverriddenPropertiesTypes = null + } + } + } + + if (lowerBoundOfOverriddenPropertiesTypes != null) { + actions.add(ChangeVariableTypeFix(property, lowerBoundOfOverriddenPropertiesTypes)) + } + + if (overriddenMismatchingProperties.size == 1 && canChangeOverriddenPropertyType) { + val overriddenProperty = DescriptorToSourceUtils.descriptorToDeclaration(overriddenMismatchingProperties[0]) + if (overriddenProperty is KtProperty) { + actions.add(ChangeVariableTypeFix(overriddenProperty, propertyType!!)) + } + } + } + + return actions + } + } + } } }