diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt index a670a167e0b..b44c7b0d318 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/createFromUsage/createFunction/CreateCallableFromUsageFix.kt @@ -37,12 +37,16 @@ public class CreateCallableFromUsageFix( val popupTitle = JetBundle.message("choose.target.class.or.trait.title") val receiverTypeCandidates = callableBuilder.computeTypeCandidates(callableInfo.receiverTypeInfo) if (receiverTypeCandidates.isNotEmpty()) { - val toPsi: (TypeCandidate) -> JetClassOrObject = { - val descriptor = DescriptorUtils.getClassDescriptorForType(it.theType) - DescriptorToDeclarationUtil.getDeclaration(file, descriptor) as JetClassOrObject - } - chooseContainerElementIfNecessary(receiverTypeCandidates, editor, popupTitle, false, toPsi) { - runBuilder(CallablePlacement.WithReceiver(it)) + // TODO: Support generation of Java class members + val containers = receiverTypeCandidates + .map { candidate -> + val descriptor = DescriptorUtils.getClassDescriptorForType(candidate.theType) + (DescriptorToDeclarationUtil.getDeclaration(file, descriptor) as? JetClassOrObject)?.let { candidate to it } + } + .filterNotNull() + + chooseContainerElementIfNecessary(containers, editor, popupTitle, false, { it.second }) { + runBuilder(CallablePlacement.WithReceiver(it.first)) } } else { diff --git a/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.after.kt b/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.after.kt new file mode 100644 index 00000000000..c1acc476392 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.after.kt @@ -0,0 +1,10 @@ +// "Create function 'foo' from usage" "true" +// ERROR: Unresolved reference: foo + +fun test(): Int { + return A().foo(1, "2") +} + +fun Any.foo(i: Int, s: String): Int { + throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.before.Main.kt b/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.before.Main.kt new file mode 100644 index 00000000000..7f2e9a9e498 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.before.Main.kt @@ -0,0 +1,6 @@ +// "Create function 'foo' from usage" "true" +// ERROR: Unresolved reference: foo + +fun test(): Int { + return A().foo(1, "2") +} \ No newline at end of file diff --git a/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.before.data.Sample.java b/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.before.data.Sample.java new file mode 100644 index 00000000000..1b4568a8f26 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.before.data.Sample.java @@ -0,0 +1,3 @@ +class A { + +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/AbstractQuickFixMultiFileTest.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/AbstractQuickFixMultiFileTest.java index 50463f364c6..06595062c54 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/AbstractQuickFixMultiFileTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/AbstractQuickFixMultiFileTest.java @@ -24,8 +24,16 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.psi.PsiFile; +import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; +import jet.runtime.typeinfo.JetValueParameter; import junit.framework.ComparisonFailure; +import kotlin.Function1; +import kotlin.KotlinPackage; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.InTextDirectivesUtils; import org.jetbrains.jet.JetTestCaseBuilder; import org.jetbrains.jet.lang.psi.JetFile; @@ -35,6 +43,7 @@ import org.jetbrains.jet.plugin.PluginTestCaseBase; import org.jetbrains.jet.testing.ConfigLibraryUtil; import java.io.File; +import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -62,14 +71,44 @@ public abstract class AbstractQuickFixMultiFileTest extends KotlinDaemonAnalyzer } private void doTest(final String beforeFileName, boolean withExtraFile) throws Exception { - final String originalFileText = FileUtil.loadFile(new File(getTestDataPath() + beforeFileName), true); + final String testDataPath = getTestDataPath(); + File mainFile = new File(testDataPath + beforeFileName); + final String originalFileText = FileUtil.loadFile(mainFile, true); if (InTextDirectivesUtils.findStringWithPrefixes(originalFileText, "// WITH_RUNTIME") != null) { ConfigLibraryUtil.configureKotlinRuntime(myModule, PluginTestCaseBase.fullJdk()); } if (withExtraFile) { - configureByFiles(null, beforeFileName, beforeFileName.replace(".Main.", ".data.Sample.")); + File mainFileDir = mainFile.getParentFile(); + assert mainFileDir != null; + + final String mainFileName = mainFile.getName(); + final String extraFileNamePrefix = mainFileName.replace(".Main.kt", ".data.Sample."); + File[] extraFiles = mainFileDir.listFiles( + new FilenameFilter() { + @Override + public boolean accept(@NotNull File dir, @NotNull String name) { + return name.startsWith(extraFileNamePrefix); + } + } + ); + assert extraFiles != null; + + List testFiles = new ArrayList(); + testFiles.add(beforeFileName); + KotlinPackage.mapTo( + extraFiles, + testFiles, + new Function1() { + @Override + public String invoke(File file) { + return beforeFileName.replace(mainFileName, file.getName()); + } + } + ); + + configureByFiles(null, ArrayUtil.toStringArray(testFiles)); } else { configureByFiles(null, beforeFileName); @@ -79,12 +118,16 @@ public abstract class AbstractQuickFixMultiFileTest extends KotlinDaemonAnalyzer @Override public void run() { try { - Pair pair = LightQuickFixTestCase.parseActionHint(getFile(), originalFileText); + PsiFile psiFile = getFile(); + + Pair pair = LightQuickFixTestCase.parseActionHint(psiFile, originalFileText); String text = pair.getFirst(); boolean actionShouldBeAvailable = pair.getSecond(); - DirectiveBasedActionUtils.checkForUnexpectedErrors((JetFile) getFile()); + if (psiFile instanceof JetFile) { + DirectiveBasedActionUtils.checkForUnexpectedErrors((JetFile) psiFile); + } doAction(text, actionShouldBeAvailable, beforeFileName); } diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixMultiFileTestGenerated.java index 650575596c5..a300360db86 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixMultiFileTestGenerated.java @@ -227,13 +227,29 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes @TestMetadata("idea/testData/quickfix/createFromUsage/createFunction") @TestDataPath("$PROJECT_ROOT") - @InnerTestClasses({}) + @InnerTestClasses({CreateFunction.Call.class}) @RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class) public static class CreateFunction extends AbstractQuickFixMultiFileTest { public void testAllFilesPresentInCreateFunction() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createFunction"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true); } + @TestMetadata("idea/testData/quickfix/createFromUsage/createFunction/call") + @TestDataPath("$PROJECT_ROOT") + @RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class) + public static class Call extends AbstractQuickFixMultiFileTest { + public void testAllFilesPresentInCall() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/createFromUsage/createFunction/call"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true); + } + + @TestMetadata("funOnJavaType.before.Main.kt") + public void testFunOnJavaType() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/funOnJavaType.before.Main.kt"); + doTestWithExtraFile(fileName); + } + + } + } @TestMetadata("idea/testData/quickfix/createFromUsage/createVariable")