diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java index f0d77b6c27e..e824cacbd4f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiUtil.java @@ -145,49 +145,37 @@ public class JetPsiUtil { } @Nullable - public static FqName getFQName(@NotNull JetClassOrObject jetClass) { - if (jetClass.getName() == null) { - return null; - } - - PsiElement parent = jetClass.getParent(); - if (parent instanceof JetFile) { - return makeFQName(getFQName((JetFile) parent), jetClass); - } - while (parent instanceof JetClassBody) { - parent = parent.getParent(); - if (parent instanceof JetObjectDeclaration && parent.getParent() instanceof JetClassObject) { - parent = parent.getParent().getParent(); + public static FqName getFQName(JetNamedDeclaration namedDeclaration) { + if (namedDeclaration instanceof JetObjectDeclarationName) { + JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(namedDeclaration, JetObjectDeclaration.class); + if (objectDeclaration == null) { + return null; } - } - if (parent instanceof JetClassOrObject) { - return makeFQName(getFQName(((JetClassOrObject) parent)), jetClass); - } - return new FqName(jetClass.getName()); - } - @Nullable - public static FqName getFQName(@NotNull JetNamedFunction jetNamedFunction) { + return getFQName(objectDeclaration); + } - String functionName = jetNamedFunction.getName(); + String functionName = namedDeclaration.getName(); if (functionName == null) { return null; } - @SuppressWarnings("unchecked") - PsiElement qualifiedElement = PsiTreeUtil.getParentOfType( - jetNamedFunction, - JetFile.class, JetClassOrObject.class, JetNamedFunction.class); + PsiElement parent = namedDeclaration.getParent(); + if (parent instanceof JetClassBody) { + // One nesting to JetClassBody doesn't affect to qualified name + parent = parent.getParent(); + } - FqName firstPart = FqName.ROOT; - if (qualifiedElement instanceof JetFile) { - firstPart = getFQName((JetFile) qualifiedElement); + FqName firstPart = null; + if (parent instanceof JetFile) { + firstPart = getFQName((JetFile) parent); } - else if (qualifiedElement instanceof JetClassOrObject) { - firstPart = getFQName((JetClassOrObject) qualifiedElement); + else if (parent instanceof JetNamedDeclaration) { + firstPart = getFQName((JetNamedDeclaration) parent); } - else if (qualifiedElement instanceof JetNamedFunction) { - firstPart = getFQName((JetNamedFunction) qualifiedElement); + + if (firstPart == null) { + return null; } return firstPart.child(functionName); diff --git a/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java b/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java index bd80da0be3a..1b08434168e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java +++ b/compiler/frontend/src/org/jetbrains/jet/util/QualifiedNamesUtil.java @@ -130,7 +130,7 @@ public final class QualifiedNamesUtil { } public static boolean isImported(@NotNull ImportPath alreadyImported, @NotNull FqName fqName) { - if (alreadyImported.isAllUnder()) { + if (alreadyImported.isAllUnder() && !fqName.isRoot()) { return alreadyImported.fqnPart().equals(fqName.parent()); } diff --git a/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java b/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java index 9adc238ec7f..3d0103d9ed0 100644 --- a/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java +++ b/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java @@ -83,9 +83,17 @@ public class JetImportOptimizer implements ImportOptimizer { // Remove imports List imports = jetFile.getImportDirectives(); if (!imports.isEmpty()) { - jetFile.deleteChildRange( - getWithPreviousWhitespaces(imports.get(0)), - getWithFollowedWhitespaces(imports.get(imports.size() - 1))); + PsiElement firstForDelete = getWithPreviousWhitespaces(imports.get(0)); + PsiElement lastForDelete = getWithFollowedWhitespaces(imports.get(imports.size() - 1)); + + // Should be found before deletion + PsiElement elementBeforeImports = firstForDelete.getPrevSibling(); + + jetFile.deleteChildRange(firstForDelete, lastForDelete); + + if (elementBeforeImports != null) { + jetFile.addAfter(JetPsiFactory.createWhiteSpace(jetFile.getProject(), "\n"), elementBeforeImports); + } } // Insert back only necessary imports in correct order @@ -120,7 +128,7 @@ public class JetImportOptimizer implements ImportOptimizer { return false; } - public static Set extractUsedQualifiedNames(JetFile jetFile) { + public static Set extractUsedQualifiedNames(final JetFile jetFile) { final Set usedQualifiedNames = new HashSet(); jetFile.accept(new JetVisitorVoid() { @Override @@ -131,7 +139,9 @@ public class JetImportOptimizer implements ImportOptimizer { @Override public void visitReferenceExpression(JetReferenceExpression expression) { - if (PsiTreeUtil.getParentOfType(expression, JetImportDirective.class) == null) { + if (PsiTreeUtil.getParentOfType(expression, JetImportDirective.class) == null && + PsiTreeUtil.getParentOfType(expression, JetNamespaceHeader.class) == null) { + PsiReference reference = expression.getReference(); if (reference != null) { List references = new ArrayList(); @@ -141,7 +151,7 @@ public class JetImportOptimizer implements ImportOptimizer { } if (references.isEmpty() && reference instanceof PsiPolyVariantReference) { - for (ResolveResult resolveResult : ((PsiPolyVariantReference) reference).multiResolve(true)) { + for (ResolveResult resolveResult : ((PsiPolyVariantReference)reference).multiResolve(true)) { references.add(resolveResult.getElement()); } } @@ -153,7 +163,6 @@ public class JetImportOptimizer implements ImportOptimizer { } } } - } super.visitReferenceExpression(expression); @@ -166,18 +175,22 @@ public class JetImportOptimizer implements ImportOptimizer { @Nullable public static FqName getElementUsageFQName(PsiElement element) { - if (element instanceof JetClassOrObject) { - return JetPsiUtil.getFQName((JetClassOrObject) element); + if (element instanceof JetFile) { + return JetPsiUtil.getFQName((JetFile) element); } - if (element instanceof JetNamedFunction) { - return JetPsiUtil.getFQName((JetNamedFunction) element); + + if (element instanceof JetNamedDeclaration) { + return JetPsiUtil.getFQName((JetNamedDeclaration) element); } + if (element instanceof PsiClass) { String qualifiedName = ((PsiClass) element).getQualifiedName(); if (qualifiedName != null) { return new FqName(qualifiedName); } } + + // TODO: Still problem with kotlin global properties imported from class files if (element instanceof PsiMethod) { PsiMethod method = (PsiMethod) element; @@ -201,6 +214,10 @@ public class JetImportOptimizer implements ImportOptimizer { } } + if (element instanceof PsiPackage) { + return new FqName(((PsiPackage) element).getQualifiedName()); + } + return null; } diff --git a/idea/testData/editor/optimizeImports/UnusedImports.kt b/idea/testData/editor/optimizeImports/UnusedImports.kt index 9d371708340..e1a5b931d66 100644 --- a/idea/testData/editor/optimizeImports/UnusedImports.kt +++ b/idea/testData/editor/optimizeImports/UnusedImports.kt @@ -5,9 +5,15 @@ import java.net.HttpRetryException import java.util.ArrayList import kotlin.util.measureTimeMillis import java.util.HashMap +import kotlin.test.asserter +import kotlin.test.Asserter +import kotlin.Assertions class Action { fun test() { + // val traait : Asserter = asserter + val traait : Asserter? = null + val objectImport : Assertions? = null measureTimeMillis({ println(HashMap().size()) }) val test : ArrayList? = null } diff --git a/idea/testData/editor/optimizeImports/UnusedImports_after.kt b/idea/testData/editor/optimizeImports/UnusedImports_after.kt index 8b49df7fdde..fe7a544c7e8 100644 --- a/idea/testData/editor/optimizeImports/UnusedImports_after.kt +++ b/idea/testData/editor/optimizeImports/UnusedImports_after.kt @@ -1,9 +1,13 @@ import java.util.ArrayList import java.util.HashMap +import kotlin.test.Asserter import kotlin.util.measureTimeMillis class Action { fun test() { + // val traait : Asserter = asserter + val traait : Asserter? = null + val objectImport : Assertions? = null measureTimeMillis({ println(HashMap().size()) }) val test : ArrayList? = null }