diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java index bc9e963014c..9cdd956b85e 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java @@ -131,6 +131,7 @@ public class JetCompletionContributor extends CompletionContributor { } } + // Iterate through the function with attempt to resolve found functions for (String functionFQN : functionFQNs) { // System.out.println(functionFQN); diff --git a/idea/testData/completion/basic/ExtensionFromStandardLibrary.kt b/idea/testData/completion/basic/ExtensionFromStandardLibrary.kt new file mode 100644 index 00000000000..f662efd8701 --- /dev/null +++ b/idea/testData/completion/basic/ExtensionFromStandardLibrary.kt @@ -0,0 +1,13 @@ +package first + +import java.util.ArrayList + +fun firstFun() { + val a = ArrayList() + a.toLinke +} + +// RUNTIME: 1 +// TIME: 2 +// EXIST: toLinkedList +// NUMBER: 1 \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-1.kt b/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-1.kt new file mode 100644 index 00000000000..9e3677e446a --- /dev/null +++ b/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-1.kt @@ -0,0 +1,10 @@ +package first + +fun firstFun() { + val a = "" + a.hello +} + +// EXIST: helloFun +// EXIST: helloFunPreventAutoInsert +// NUMBER: 2 \ No newline at end of file diff --git a/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-2.kt b/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-2.kt new file mode 100644 index 00000000000..7807436bb20 --- /dev/null +++ b/idea/testData/completion/basic/multifile/NotImportedExtensionFunction-2.kt @@ -0,0 +1,7 @@ +package second + +fun String.helloFun() { +} + +fun String.helloFunPreventAutoInsert() { +} \ No newline at end of file diff --git a/idea/testData/completion/handlers/multifile/ExtensionFunctions-1.kt b/idea/testData/completion/handlers/multifile/ExtensionFunctions-1.kt new file mode 100644 index 00000000000..9b743c13c61 --- /dev/null +++ b/idea/testData/completion/handlers/multifile/ExtensionFunctions-1.kt @@ -0,0 +1,6 @@ +package first + +fun firstFun() { + val a = "" + a.hello +} \ No newline at end of file diff --git a/idea/testData/completion/handlers/multifile/ExtensionFunctions-2.kt b/idea/testData/completion/handlers/multifile/ExtensionFunctions-2.kt new file mode 100644 index 00000000000..2f98c0a94f4 --- /dev/null +++ b/idea/testData/completion/handlers/multifile/ExtensionFunctions-2.kt @@ -0,0 +1,4 @@ +package second + +fun String.helloFun() { +} \ No newline at end of file diff --git a/idea/testData/completion/handlers/multifile/ExtensionFunctions.kt.after b/idea/testData/completion/handlers/multifile/ExtensionFunctions.kt.after new file mode 100644 index 00000000000..d2679999b61 --- /dev/null +++ b/idea/testData/completion/handlers/multifile/ExtensionFunctions.kt.after @@ -0,0 +1,8 @@ +package first + +import second.helloFun + +fun firstFun() { + val a = "" + a.helloFun() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java b/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java index 2ec8535261a..5b0b9b10783 100644 --- a/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java +++ b/idea/tests/org/jetbrains/jet/completion/ExpectedCompletionUtils.java @@ -68,17 +68,17 @@ public class ExpectedCompletionUtils { @Nullable public Integer getExpectedNumber(String fileText) { - final String[] numberStrings = findListWithPrefix(numberLinePrefix, fileText); - if (numberStrings.length > 0) { - return Integer.parseInt(numberStrings[0]); - } - - return null; + return getPrefixedInt(fileText, numberLinePrefix); } @Nullable public Integer getExecutionTime(String fileText) { - final String[] numberStrings = findListWithPrefix(executionTimePrefix, fileText); + return getPrefixedInt(fileText, executionTimePrefix); + } + + @Nullable + public static Integer getPrefixedInt(String fileText, String prefix) { + final String[] numberStrings = findListWithPrefix(prefix, fileText); if (numberStrings.length > 0) { return Integer.parseInt(numberStrings[0]); } diff --git a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java index 660e9d1f92f..24927696af2 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/JetBasicCompletionTest.java @@ -45,6 +45,10 @@ public class JetBasicCompletionTest extends JetCompletionTestBase { doTest(); } + public void testExtensionFromStandardLibrary() { + doTest(); + } + public void testFromImports() { doTest(); } @@ -101,6 +105,8 @@ public class JetBasicCompletionTest extends JetCompletionTestBase { doTest(); } + + @Override protected String getTestDataPath() { return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/basic").getPath() + diff --git a/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java b/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java index 4c832c5cee6..a9218f58514 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java +++ b/idea/tests/org/jetbrains/jet/completion/JetCompletionTestBase.java @@ -22,7 +22,12 @@ import com.intellij.codeInsight.completion.LightCompletionTestCase; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupManager; import com.intellij.codeInsight.lookup.impl.LookupImpl; +import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import org.apache.commons.lang.SystemUtils; +import org.jetbrains.jet.plugin.JetWithJdkAndRuntimeLightProjectDescriptor; import org.jetbrains.jet.plugin.PluginTestCaseBase; /** @@ -47,32 +52,71 @@ public abstract class JetCompletionTestBase extends LightCompletionTestCase { final String fileText = getFile().getText(); - Integer completionTime = completionUtils.getExecutionTime(fileText); - - complete(completionTime == null ? 1 : completionTime); + boolean withKotlinRuntime = ExpectedCompletionUtils.getPrefixedInt(fileText, "// RUNTIME:") != null; - final String[] expected = completionUtils.itemsShouldExist(fileText); - final String[] unexpected = completionUtils.itemsShouldAbsent(fileText); - Integer itemsNumber = completionUtils.getExpectedNumber(fileText); + try { + if (withKotlinRuntime) { + configureWithKotlinRuntime(); + } - assertTrue("Should be some assertions about completion", expected.length != 0 || unexpected.length != 0 || itemsNumber != null); + Integer completionTime = completionUtils.getExecutionTime(fileText); - assertContainsItems(expected); - assertNotContainItems(unexpected); + complete(completionTime == null ? 1 : completionTime); - if (itemsNumber != null) { - assertEquals(itemsNumber.intValue(), myItems.length); + final String[] expected = completionUtils.itemsShouldExist(fileText); + final String[] unexpected = completionUtils.itemsShouldAbsent(fileText); + Integer itemsNumber = completionUtils.getExpectedNumber(fileText); + + assertTrue("Should be some assertions about completion", expected.length != 0 || unexpected.length != 0 || itemsNumber != null); + + assertContainsItems(expected); + assertNotContainItems(unexpected); + + if (itemsNumber != null) { + assertEquals(itemsNumber.intValue(), myItems.length); + } } + finally { + if (withKotlinRuntime) { + unConfigureKotlinRuntime(); + } + } + + } catch (Exception e) { throw new AssertionError(e); } } + protected static void configureWithKotlinRuntime() { + final ModuleRootManager rootManager = ModuleRootManager.getInstance(getModule()); + final ModifiableRootModel rootModel = rootManager.getModifiableModel(); + + rootModel.setSdk(getFullJavaJDK()); + JetWithJdkAndRuntimeLightProjectDescriptor.INSTANCE.configureModule(getModule(), rootModel, null); + + rootModel.commit(); + } + + protected void unConfigureKotlinRuntime() { + final ModuleRootManager rootManager = ModuleRootManager.getInstance(getModule()); + final ModifiableRootModel rootModel = rootManager.getModifiableModel(); + + rootModel.setSdk(getProjectJDK()); + JetWithJdkAndRuntimeLightProjectDescriptor.unConfigureModule(rootModel); + + rootModel.commit(); + } + @Override protected Sdk getProjectJDK() { return PluginTestCaseBase.jdkFromIdeaHome(); } + protected static Sdk getFullJavaJDK() { + return JavaSdk.getInstance().createJdk("JDK", SystemUtils.getJavaHome().getAbsolutePath()); + } + @Override protected void complete(final int time) { new CodeCompletionHandlerBase(type, false, false, true).invokeCompletion(getProject(), getEditor(), time, false); diff --git a/idea/tests/org/jetbrains/jet/completion/JetMultifileBasicCompletionTest.java b/idea/tests/org/jetbrains/jet/completion/JetMultifileBasicCompletionTest.java index 66c76b9d1cf..71b6e4a6cca 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetMultifileBasicCompletionTest.java +++ b/idea/tests/org/jetbrains/jet/completion/JetMultifileBasicCompletionTest.java @@ -27,6 +27,10 @@ public class JetMultifileBasicCompletionTest extends JetCompletionMultiTestBase doFileTest(2); } + public void testNotImportedExtensionFunction() throws Exception { + doFileTest(2); + } + public void testExtensionFunction() throws Exception { // TODO: fix and uncomment // doFileTest(); diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java index 68e78e1c80e..e6311d8e58a 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java +++ b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionMultifileHandlerTest.java @@ -26,6 +26,10 @@ import java.io.File; */ public class CompletionMultifileHandlerTest extends CompletionTestCase { + public void testExtensionFunctions() throws Exception { + doTest(); + } + public void testTopLevelFunctionImport() throws Exception { doTest(); } diff --git a/idea/tests/org/jetbrains/jet/plugin/JetWithJdkAndRuntimeLightProjectDescriptor.java b/idea/tests/org/jetbrains/jet/plugin/JetWithJdkAndRuntimeLightProjectDescriptor.java index a698d4fea2b..e666476b25f 100644 --- a/idea/tests/org/jetbrains/jet/plugin/JetWithJdkAndRuntimeLightProjectDescriptor.java +++ b/idea/tests/org/jetbrains/jet/plugin/JetWithJdkAndRuntimeLightProjectDescriptor.java @@ -21,14 +21,14 @@ import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.roots.ContentEntry; -import com.intellij.openapi.roots.ModifiableRootModel; -import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.LightProjectDescriptor; import org.apache.commons.lang.SystemUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.ForTestCompileStdlib; /** @@ -52,11 +52,25 @@ public class JetWithJdkAndRuntimeLightProjectDescriptor implements LightProjectD } @Override - public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) { + public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @Nullable ContentEntry contentEntry) { Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary("ktl").getModifiableModel(); VirtualFile cd = JarFileSystem.getInstance().findFileByPath(ForTestCompileStdlib.stdlibJarForTests() + "!/"); assert cd != null; modifiableModel.addRoot(cd, OrderRootType.CLASSES); modifiableModel.commit(); } + + public static void unConfigureModule(@NotNull ModifiableRootModel model) { + for (OrderEntry orderEntry : model.getOrderEntries()) { + if (orderEntry instanceof LibraryOrderEntry) { + LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry) orderEntry; + + Library library = libraryOrderEntry.getLibrary(); + if (library != null && library.getName().equals("ktl")) { + model.getModuleLibraryTable().removeLibrary(library); + break; + } + } + } + } }