diff --git a/.idea/dictionaries/valentin.xml b/.idea/dictionaries/valentin.xml index 70d806d6359..54354129c96 100644 --- a/.idea/dictionaries/valentin.xml +++ b/.idea/dictionaries/valentin.xml @@ -2,6 +2,7 @@ initializers + inserter pparent rparenth diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt b/idea/idea-analysis/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt index 1bc295aef55..bad12afb0ff 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/codeInsight/ShortenReferences.kt @@ -103,13 +103,13 @@ public object ShortenReferences { private fun process(elements: Iterable, elementFilter: (PsiElement) -> FilterResult) { for ((file, fileElements) in elements.groupBy { element -> element.getContainingJetFile() }) { - ImportInsertHelper.getInstance().optimizeImportsOnTheFly(file) + val importInserter = ImportInserter(file) // first resolve all qualified references - optimization val referenceToContext = JetFileReferencesResolver.resolve(file, fileElements, resolveShortNames = false) - processElements(fileElements, ShortenTypesVisitor(file, elementFilter, referenceToContext)) - processElements(fileElements, ShortenQualifiedExpressionsVisitor(file, elementFilter, referenceToContext)) + processElements(fileElements, ShortenTypesVisitor(file, elementFilter, referenceToContext, importInserter)) + processElements(fileElements, ShortenQualifiedExpressionsVisitor(file, elementFilter, referenceToContext, importInserter)) } } @@ -123,7 +123,8 @@ public object ShortenReferences { private abstract class ShorteningVisitor( val file: JetFile, val elementFilter: (PsiElement) -> FilterResult, - val resolveMap: Map) : JetVisitorVoid() { + val resolveMap: Map, + val importInserter: ImportInserter) : JetVisitorVoid() { protected val resolveSession: ResolveSessionForBodies get() = file.getLazyResolveSession() @@ -150,8 +151,9 @@ public object ShortenReferences { private class ShortenTypesVisitor( file: JetFile, elementFilter: (PsiElement) -> FilterResult, - resolveMap: Map - ) : ShorteningVisitor(file, elementFilter, resolveMap) { + resolveMap: Map, + importInserter: ImportInserter + ) : ShorteningVisitor(file, elementFilter, resolveMap, importInserter) { private fun canShortenType(userType: JetUserType): Boolean { if (userType.getQualifier() == null) return false val referenceExpression = userType.getReferenceExpression() @@ -169,13 +171,17 @@ public object ShortenReferences { if (targetByName == null) { if (target.getContainingDeclaration() is ClassDescriptor) return false - addImport(target, file) + importInserter.addImport(target) return true } else if (target.asString() == targetByName.asString()) { return true } else { + if (importInserter.optimizeImports()) { + return canShortenType(userType) // if we have optimized imports then try again + } + // leave FQ name return false } @@ -206,8 +212,9 @@ public object ShortenReferences { private class ShortenQualifiedExpressionsVisitor( file: JetFile, elementFilter: (PsiElement) -> FilterResult, - resolveMap: Map - ) : ShorteningVisitor(file, elementFilter, resolveMap) { + resolveMap: Map, + importInserter: ImportInserter + ) : ShorteningVisitor(file, elementFilter, resolveMap, importInserter) { private fun adjustDescriptor(it: DeclarationDescriptor): DeclarationDescriptor { return (it as? ConstructorDescriptor)?.getContainingDeclaration() ?: it } @@ -238,19 +245,25 @@ public object ShortenReferences { val newContext = selectorCopy.analyzeInContext(scope) val targetsAfter = (selectorCopy.getCalleeExpressionIfAny() as JetReferenceExpression).getTargets(newContext) - return when (targetsAfter.size) { + when (targetsAfter.size) { 0 -> { if (!isClassMember && isClassOrPackage) { - addImport(targetBefore, file) + importInserter.addImport(targetBefore) return true } - false + return false } - 1 -> targetBefore == targetsAfter.first() - - else -> false + 1 -> { + if (targetBefore == targetsAfter.first()) return true + } } + + if (importInserter.optimizeImports()) { + return canShorten(qualifiedExpression) // if we have optimized imports then try again + } + + return false } override fun visitDotQualifiedExpression(expression: JetDotQualifiedExpression) { @@ -273,7 +286,19 @@ public object ShortenReferences { private fun DeclarationDescriptor.asString() = DescriptorRenderer.FQ_NAMES_IN_TYPES.render(this) - private fun addImport(descriptor: DeclarationDescriptor, file: JetFile) { - ImportInsertHelper.getInstance().writeImportToFile(ImportPath(DescriptorUtils.getFqNameSafe(descriptor), false), file) + // this class is needed to optimize imports only when we actually insert any import (optimization) + private class ImportInserter(val file: JetFile) { + private var optimizeImports = true + + fun addImport(descriptor: DeclarationDescriptor) { + optimizeImports() + ImportInsertHelper.getInstance().writeImportToFile(ImportPath(DescriptorUtils.getFqNameSafe(descriptor), false), file) + } + + fun optimizeImports(): Boolean { + if (!optimizeImports) return false + optimizeImports = false + return ImportInsertHelper.getInstance().optimizeImportsOnTheFly(file) + } } } diff --git a/idea/idea-analysis/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java b/idea/idea-analysis/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java index eaf6859ecf2..c75c0b38bd3 100644 --- a/idea/idea-analysis/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java +++ b/idea/idea-analysis/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelper.java @@ -32,6 +32,8 @@ public abstract class ImportInsertHelper { public abstract void addImportDirectiveIfNeeded(@NotNull FqName importFqn, @NotNull JetFile file); + public abstract boolean optimizeImportsOnTheFly(JetFile file); + public abstract boolean isImportedWithDefault(@NotNull ImportPath importPath, @NotNull JetFile contextFile); public abstract boolean needImport(@NotNull FqName fqName, @NotNull JetFile file); @@ -39,6 +41,5 @@ public abstract class ImportInsertHelper { public abstract boolean needImport(@NotNull ImportPath importPath, @NotNull JetFile file); public abstract boolean needImport(@NotNull ImportPath importPath, @NotNull JetFile file, List importDirectives); - public abstract void optimizeImportsOnTheFly(JetFile file); public abstract void writeImportToFile(@NotNull ImportPath importPath, @NotNull JetFile file); } diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelperImpl.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelperImpl.java index 33f2f813b4d..33933e14413 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelperImpl.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportInsertHelperImpl.java @@ -50,12 +50,17 @@ public class ImportInsertHelperImpl extends ImportInsertHelper { } @Override - public void optimizeImportsOnTheFly(JetFile file) { + public boolean optimizeImportsOnTheFly(JetFile file) { if (CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) { new OptimizeImportsProcessor(file.getProject(), file).runWithoutProgress(); + return true; + } + else { + return false; } } + @Override public void writeImportToFile(@NotNull ImportPath importPath, @NotNull JetFile file) { JetPsiFactory psiFactory = JetPsiFactory(file.getProject()); if (file instanceof JetCodeFragment) {