diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/DescriptorsUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/DescriptorsUtils.java deleted file mode 100644 index f28f1ec954c..00000000000 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/DescriptorsUtils.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.jetbrains.jet.lang.descriptors; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.util.QualifiedNamesUtil; - -/** - * @author Nikolay Krasko - */ -public final class DescriptorsUtils { - - private DescriptorsUtils() { - } - - public static String getFQName(@NotNull NamespaceDescriptor namespaceDescriptor) { - - NamespaceDescriptor tempNamespace = namespaceDescriptor; - String fqn = tempNamespace.getName(); - - while (tempNamespace.getContainingDeclaration() instanceof NamespaceDescriptor) { - tempNamespace = (NamespaceDescriptor) tempNamespace.getContainingDeclaration(); - - assert tempNamespace != null; - fqn = tempNamespace.getName() + "." + fqn; - } - - return fqn; - } - - public static String getFQName(@NotNull NamedFunctionDescriptor functionDescriptor) { - if (functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) { - final String namespaceFQN = getFQName((NamespaceDescriptor) functionDescriptor.getContainingDeclaration()); - return QualifiedNamesUtil.combine(namespaceFQN, functionDescriptor.getName()); - } - - throw new IllegalArgumentException("Currently supported only for top level functions"); - } - - public static boolean isTopLevelFunction(@NotNull NamedFunctionDescriptor functionDescriptor) { - return functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor; - } -} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index 31e995218d6..51a0b9b2e2f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -1,23 +1,16 @@ package org.jetbrains.jet.lang.resolve; -import com.google.common.base.Function; -import com.google.common.base.Predicate; -import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.psi.JetObjectDeclaration; -import org.jetbrains.jet.lang.psi.JetObjectDeclarationName; -import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.*; -import org.jetbrains.jet.lang.types.checker.JetTypeChecker; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Set; import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER; @@ -175,6 +168,10 @@ public class DescriptorUtils { return descriptor.getName(); } + public static boolean isTopLevelFunction(@NotNull NamedFunctionDescriptor functionDescriptor) { + return functionDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor; + } + @Nullable public static D getParentOfType(@Nullable DeclarationDescriptor descriptor, @NotNull Class aClass) { return getParentOfType(descriptor, aClass, true); diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java index c3840eb2675..b7a5e8ed21c 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java @@ -4,14 +4,18 @@ import com.intellij.codeInsight.AutoPopupController; import com.intellij.codeInsight.completion.InsertHandler; import com.intellij.codeInsight.completion.InsertionContext; import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.DescriptorsUtils; import org.jetbrains.jet.lang.descriptors.NamedFunctionDescriptor; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetQualifiedExpression; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.plugin.completion.JetLookupObject; import org.jetbrains.jet.plugin.quickfix.ImportClassHelper; @@ -38,7 +42,10 @@ public class JetFunctionInsertHandler implements InsertHandler { int startOffset = context.getStartOffset(); PsiElement element = context.getFile().findElementAt(startOffset); - if (element == null) return; + if (element == null) { + return; + } + int lookupStringLength = item.getLookupString().length(); int endOffset = startOffset + lookupStringLength; Document document = context.getDocument(); @@ -63,22 +70,43 @@ public class JetFunctionInsertHandler implements InsertHandler { PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getDocument()); - // Should be done after all string insertions and document commitment. addImport(context, item); } - private static void addImport(InsertionContext context, LookupElement item) { - if (context.getFile() instanceof JetFile && item.getObject() instanceof JetLookupObject) { - final DeclarationDescriptor descriptor = ((JetLookupObject) item.getObject()).getDescriptor(); - if (descriptor instanceof NamedFunctionDescriptor) { + private static void addImport(final InsertionContext context, final @NotNull LookupElement item) { + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + int startOffset = context.getStartOffset(); + PsiElement element = context.getFile().findElementAt(startOffset); + if (element == null) { + return; + } - JetFile file = (JetFile) context.getFile(); - NamedFunctionDescriptor functionDescriptor = (NamedFunctionDescriptor) descriptor; + // No auto import for qualified expressions + if (PsiTreeUtil.getParentOfType(element, JetQualifiedExpression.class) != null) { + return; + } - if (DescriptorsUtils.isTopLevelFunction(functionDescriptor)) { - ImportClassHelper.addImportDirective(DescriptorsUtils.getFQName(functionDescriptor), file); + if (context.getFile() instanceof JetFile && item.getObject() instanceof JetLookupObject) { + final DeclarationDescriptor descriptor = ((JetLookupObject) item.getObject()).getDescriptor(); + if (descriptor instanceof NamedFunctionDescriptor) { + + final JetFile file = (JetFile) context.getFile(); + NamedFunctionDescriptor functionDescriptor = (NamedFunctionDescriptor) descriptor; + final String fqn = DescriptorUtils.getFQName(functionDescriptor); + + if (DescriptorUtils.isTopLevelFunction(functionDescriptor)) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + ImportClassHelper.addImportDirective(fqn, file); + } + }); + } + } } } - } + }); } } diff --git a/idea/testData/completion/handlers/multifile/TopLevelFunctionInQualifiedExpr-1.kt b/idea/testData/completion/handlers/multifile/TopLevelFunctionInQualifiedExpr-1.kt new file mode 100644 index 00000000000..62ef681718e --- /dev/null +++ b/idea/testData/completion/handlers/multifile/TopLevelFunctionInQualifiedExpr-1.kt @@ -0,0 +1,7 @@ +package some + +import jettesting.* + +fun other() { + data.topLevelFu +} diff --git a/idea/testData/completion/handlers/multifile/TopLevelFunctionInQualifiedExpr-2.kt b/idea/testData/completion/handlers/multifile/TopLevelFunctionInQualifiedExpr-2.kt new file mode 100644 index 00000000000..39c9b80f455 --- /dev/null +++ b/idea/testData/completion/handlers/multifile/TopLevelFunctionInQualifiedExpr-2.kt @@ -0,0 +1,4 @@ +package jettesting.data + +fun topLevelFunction() { +} \ No newline at end of file diff --git a/idea/testData/completion/handlers/multifile/TopLevelFunctionInQualifiedExpr.kt.after b/idea/testData/completion/handlers/multifile/TopLevelFunctionInQualifiedExpr.kt.after new file mode 100644 index 00000000000..d3905ced711 --- /dev/null +++ b/idea/testData/completion/handlers/multifile/TopLevelFunctionInQualifiedExpr.kt.after @@ -0,0 +1,7 @@ +package some + +import jettesting.* + +fun other() { + data.topLevelFunction() +} diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java index e192c85ba5f..2257967233d 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java +++ b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java @@ -14,6 +14,10 @@ public class CompletionMultifileHandlerTest extends CompletionTestCase { doTest(); } + public void testTopLevelFunctionInQualifiedExpr() { + doTest(); + } + public void doTest() { String fileName = getTestName(false); try {