Optimization to not optimize imports on completion of class name if we do not insert any import

This commit is contained in:
Valentin Kipyatkov
2014-10-15 15:27:01 +04:00
parent 68e2e21fb9
commit cb00e729ad
4 changed files with 51 additions and 19 deletions
+1
View File
@@ -2,6 +2,7 @@
<dictionary name="valentin">
<words>
<w>initializers</w>
<w>inserter</w>
<w>pparent</w>
<w>rparenth</w>
</words>
@@ -103,13 +103,13 @@ public object ShortenReferences {
private fun process(elements: Iterable<JetElement>, 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<T : JetElement>(
val file: JetFile,
val elementFilter: (PsiElement) -> FilterResult,
val resolveMap: Map<JetReferenceExpression, BindingContext>) : JetVisitorVoid() {
val resolveMap: Map<JetReferenceExpression, BindingContext>,
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<JetReferenceExpression, BindingContext>
) : ShorteningVisitor<JetUserType>(file, elementFilter, resolveMap) {
resolveMap: Map<JetReferenceExpression, BindingContext>,
importInserter: ImportInserter
) : ShorteningVisitor<JetUserType>(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<JetReferenceExpression, BindingContext>
) : ShorteningVisitor<JetQualifiedExpression>(file, elementFilter, resolveMap) {
resolveMap: Map<JetReferenceExpression, BindingContext>,
importInserter: ImportInserter
) : ShorteningVisitor<JetQualifiedExpression>(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)
}
}
}
@@ -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<JetImportDirective> importDirectives);
public abstract void optimizeImportsOnTheFly(JetFile file);
public abstract void writeImportToFile(@NotNull ImportPath importPath, @NotNull JetFile file);
}
@@ -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) {