From 82b4304f0e6f3cb9f9634f8033238047775e69c1 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Sat, 21 Apr 2012 02:39:23 +0400 Subject: [PATCH] Added auto-importing in JetChangePropertyActions.addTypeAnnotation(). It is used in "specify type explicitly" intention and "introduce variable" refactoring. Corrected auto-importing for cases of nested classes (e.g. Map.Entry). --- .../jetbrains/jet/lang/types/TypeUtils.java | 17 ++++++++++++ .../jet/resolve/DescriptorRenderer.java | 27 +++++++++++++++---- .../jetbrains/jet/plugin/JetPluginUtil.java | 6 ----- .../OverrideImplementMethodsHandler.java | 6 ++--- .../jet/plugin/quickfix/AddReturnTypeFix.java | 2 +- .../plugin/quickfix/ImportInsertHelper.java | 26 +++++++++++++----- .../quickfix/RemovePartsFromPropertyFix.java | 2 +- .../JetChangePropertyActions.java | 6 ++++- 8 files changed, 68 insertions(+), 24 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java index 0421553c7a1..f96d11a93ed 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/TypeUtils.java @@ -529,6 +529,23 @@ public class TypeUtils { return null; } + private static void addAllClassDescriptors(@NotNull JetType type, @NotNull Set set) { + ClassDescriptor cd = getClassDescriptor(type); + if (cd != null) { + set.add(cd); + } + for (TypeProjection projection : type.getArguments()) { + addAllClassDescriptors(projection.getType(), set); + } + } + + @NotNull + public static List getAllClassDescriptors(@NotNull JetType type) { + Set classDescriptors = new HashSet(); + addAllClassDescriptors(type, classDescriptors); + return new ArrayList(classDescriptors); + } + public static boolean hasUnsubstitutedTypeParameters(JetType type) { if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) { return true; diff --git a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 92ba84da251..783499a34d0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -30,10 +30,7 @@ import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lexer.JetTokens; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; +import java.util.*; /** * @author abreslav @@ -122,6 +119,15 @@ public class DescriptorRenderer implements Renderer { } } + private static List getOuterClassesNames(ClassDescriptor cd) { + ArrayList result = new ArrayList(); + while (cd.getContainingDeclaration() instanceof ClassifierDescriptor) { + result.add(cd.getName()); + cd = (ClassDescriptor)cd.getContainingDeclaration(); + } + return result; + } + private String renderDefaultType(JetType type, boolean shortNamesOnly) { StringBuilder sb = new StringBuilder(); ClassifierDescriptor cd = type.getConstructor().getDeclarationDescriptor(); @@ -132,7 +138,18 @@ public class DescriptorRenderer implements Renderer { typeNameObject = type.getConstructor(); } else { - typeNameObject = shortNamesOnly ? cd.getName() : DescriptorUtils.getFQName(cd); + if (shortNamesOnly) { + // for nested classes qualified name should be used + typeNameObject = cd.getName(); + DeclarationDescriptor parent = cd.getContainingDeclaration(); + while (parent instanceof ClassDescriptor) { + typeNameObject = parent.getName() + "." + typeNameObject; + parent = parent.getContainingDeclaration(); + } + } + else { + typeNameObject = DescriptorUtils.getFQName(cd); + } } sb.append(typeNameObject); diff --git a/idea/src/org/jetbrains/jet/plugin/JetPluginUtil.java b/idea/src/org/jetbrains/jet/plugin/JetPluginUtil.java index 37c647ee4ff..890ea800949 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetPluginUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/JetPluginUtil.java @@ -37,12 +37,6 @@ import java.util.LinkedList; * @author svtk */ public class JetPluginUtil { - @NotNull - public static FqName computeTypeFullName(@NotNull JetType type) { - ClassDescriptor clazz = (ClassDescriptor) type.getConstructor().getDeclarationDescriptor(); - return DescriptorUtils.getFQName(clazz).toSafe(); - } - @NotNull private static LinkedList computeTypeFullNameList(JetType type) { if (type instanceof DeferredType) { diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java index 6f8f844d7c6..b82bc360996 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java @@ -131,7 +131,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns } bodyBuilder.append(descriptor.getName()).append(" : ").append(DescriptorRenderer.COMPACT.renderTypeWithShortNames( descriptor.getType())); - ImportInsertHelper.addImportDirectiveIfNeeded(descriptor.getType(), file); + ImportInsertHelper.addImportDirectivesIfNeeded(descriptor.getType(), file); String initializer = defaultInitializer(descriptor.getType(), JetStandardLibrary.getInstance()); if (initializer != null) { bodyBuilder.append(" = ").append(initializer); @@ -168,7 +168,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns bodyBuilder.append(" : "); bodyBuilder.append(DescriptorRenderer.COMPACT.renderTypeWithShortNames(parameterDescriptor.getType())); - ImportInsertHelper.addImportDirectiveIfNeeded(parameterDescriptor.getType(), file); + ImportInsertHelper.addImportDirectivesIfNeeded(parameterDescriptor.getType(), file); if (!isAbstractFun) { delegationBuilder.append(parameterDescriptor.getName()); @@ -184,7 +184,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns boolean returnsNotUnit = returnType != null && !stdlib.getTuple0Type().equals(returnType); if (returnsNotUnit) { bodyBuilder.append(" : ").append(DescriptorRenderer.COMPACT.renderTypeWithShortNames(returnType)); - ImportInsertHelper.addImportDirectiveIfNeeded(returnType, file); + ImportInsertHelper.addImportDirectivesIfNeeded(returnType, file); } bodyBuilder.append("{").append(returnsNotUnit && !isAbstractFun ? "return " : "").append(delegationBuilder.toString()).append("}"); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AddReturnTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AddReturnTypeFix.java index 006cb2c3878..6a55bbfd471 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/AddReturnTypeFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AddReturnTypeFix.java @@ -68,7 +68,7 @@ public class AddReturnTypeFix extends JetIntentionAction { assert element instanceof JetFunction; newElement = addFunctionType(project, (JetFunction) element, type); } - ImportInsertHelper.addImportDirectiveIfNeeded(type, (JetFile) file); + ImportInsertHelper.addImportDirectivesIfNeeded(type, (JetFile)file); element.replace(newElement); } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java index 42dc1a79121..9dc612eda86 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java @@ -17,22 +17,21 @@ package org.jetbrains.jet.plugin.quickfix; import com.intellij.psi.PsiElement; -import com.intellij.usages.impl.rules.NonCodeUsageGroupingRule; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.DefaultModuleConfiguration; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetImportDirective; import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.psi.JetPsiUtil; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingContextUtils; -import org.jetbrains.jet.lang.resolve.FqName; -import org.jetbrains.jet.lang.resolve.ImportPath; +import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.java.JavaBridgeConfiguration; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.plugin.JetPluginUtil; import org.jetbrains.jet.util.QualifiedNamesUtil; @@ -53,7 +52,7 @@ public class ImportInsertHelper { * @param type type to import * @param file file where import directive should be added */ - public static void addImportDirectiveIfNeeded(@NotNull JetType type, @NotNull JetFile file) { + public static void addImportDirectivesIfNeeded(@NotNull JetType type, @NotNull JetFile file) { if (JetPluginUtil.checkTypeIsStandard(type, file.getProject()) || ErrorUtils.isErrorType(type)) { return; } @@ -62,7 +61,9 @@ public class ImportInsertHelper { if (element != null && element.getContainingFile() == file) { //declaration is in the same file, so no import is needed return; } - addImportDirective(JetPluginUtil.computeTypeFullName(type), file); + for (ClassDescriptor clazz : TypeUtils.getAllClassDescriptors(type)) { + addImportDirective(DescriptorUtils.getFQName(getTopLevelClass(clazz)).toSafe(), file); + } } /** @@ -155,4 +156,15 @@ public class ImportInsertHelper { return true; } + + private static ClassDescriptor getTopLevelClass(ClassDescriptor classDescriptor) { + while (true) { + DeclarationDescriptor parent = classDescriptor.getContainingDeclaration(); + if (parent instanceof ClassDescriptor) { + classDescriptor = (ClassDescriptor) parent; + } else { + return classDescriptor; + } + } + } } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java index 886ea3ea8ed..f67c6452cb3 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/RemovePartsFromPropertyFix.java @@ -119,7 +119,7 @@ public class RemovePartsFromPropertyFix extends JetIntentionAction } } if (needImport) { - ImportInsertHelper.addImportDirectiveIfNeeded(type, (JetFile) file); + ImportInsertHelper.addImportDirectivesIfNeeded(type, (JetFile)file); } element.replace(newElement); } diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetChangePropertyActions.java b/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetChangePropertyActions.java index 8cd70130ea4..eef765ba774 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetChangePropertyActions.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetChangePropertyActions.java @@ -5,10 +5,13 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiWhiteSpace; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetProperty; import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.psi.JetTypeReference; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper; +import org.jetbrains.jet.resolve.DescriptorRenderer; /** * User: Alefas @@ -35,13 +38,14 @@ public class JetChangePropertyActions { if (anchor == null) return; anchor = anchor.getNextSibling(); if (anchor == null || !(anchor instanceof PsiWhiteSpace)) return; - JetTypeReference typeReference = JetPsiFactory.createType(project, exprType.toString()); + JetTypeReference typeReference = JetPsiFactory.createType(project, DescriptorRenderer.TEXT.renderTypeWithShortNames(exprType)); ASTNode colon = JetPsiFactory.createColonNode(project); ASTNode anchorNode = anchor.getNode().getTreeNext(); property.getNode().addChild(colon, anchorNode); property.getNode().addChild(JetPsiFactory.createWhiteSpace(project).getNode(), anchorNode); property.getNode().addChild(typeReference.getNode(), anchorNode); property.getNode().addChild(JetPsiFactory.createWhiteSpace(project).getNode(), anchorNode); + ImportInsertHelper.addImportDirectivesIfNeeded(exprType, (JetFile)property.getContainingFile()); anchor.delete(); }