diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 2e138321e47..c0f4f863924 100644 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -60,6 +60,7 @@ import org.jetbrains.kotlin.idea.completion.test.weighers.AbstractSmartCompletio import org.jetbrains.kotlin.idea.configuration.AbstractConfigureProjectByChangingFileTest import org.jetbrains.kotlin.idea.conversion.copy.AbstractJavaToKotlinCopyPasteConversionTest import org.jetbrains.kotlin.idea.coverage.AbstractKotlinCoverageOutputFilesTest +import org.jetbrains.kotlin.idea.debugger.AbstractBeforeExtractFunctionInsertionTest import org.jetbrains.kotlin.idea.debugger.AbstractKotlinSteppingTest import org.jetbrains.kotlin.idea.debugger.AbstractPositionManagerTest import org.jetbrains.kotlin.idea.debugger.AbstractSmartStepIntoTest @@ -681,6 +682,10 @@ fun main(args: Array) { model("debugger/smartStepInto") } + testClass() { + model("debugger/insertBeforeExtractFunction", extension = "kt") + } + testClass() { model("debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto", testMethod = "doStepIntoTest", testClassName = "StepInto") model("debugger/tinyApp/src/stepping/stepIntoAndSmartStepInto", testMethod = "doSmartStepIntoTest", testClassName = "SmartStepInto") diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt index 2b0409290e6..19c94e77473 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/evaluate/extractFunctionForDebuggerUtil.kt @@ -71,15 +71,9 @@ fun getFunctionForExtractedFragment( fun generateFunction(): ExtractionResult? { val originalFile = breakpointFile as KtFile - val tmpFile = originalFile.createTempCopy { it } - tmpFile.suppressDiagnosticsInDebugMode = true - - val contextElement = getExpressionToAddDebugExpressionBefore(tmpFile, codeFragment.context, breakpointLine) ?: return null - - addImportsToFile(codeFragment.importsAsImportList(), tmpFile) - - val newDebugExpressions = addDebugExpressionBeforeContextElement(codeFragment, contextElement) + val newDebugExpressions = addDebugExpressionIntoTmpFileForExtractFunction(originalFile, codeFragment, breakpointLine) if (newDebugExpressions.isEmpty()) return null + val tmpFile = newDebugExpressions.first().getContainingKtFile() val targetSibling = tmpFile.declarations.firstOrNull() ?: return null @@ -107,29 +101,34 @@ fun getFunctionForExtractedFragment( return runReadAction { generateFunction() } } +fun addDebugExpressionIntoTmpFileForExtractFunction(originalFile: KtFile, codeFragment: KtCodeFragment, line: Int): List { + val tmpFile = originalFile.createTempCopy { it } + tmpFile.suppressDiagnosticsInDebugMode = true + + val contextElement = getExpressionToAddDebugExpressionBefore(tmpFile, codeFragment.context, line) ?: return emptyList() + + addImportsToFile(codeFragment.importsAsImportList(), tmpFile) + + return addDebugExpressionBeforeContextElement(codeFragment, contextElement) +} + private fun addImportsToFile(newImportList: KtImportList?, tmpFile: KtFile) { - if (newImportList != null) { + if (newImportList != null && newImportList.imports.isNotEmpty()) { val tmpFileImportList = tmpFile.importList - val packageDirective = tmpFile.packageDirective val psiFactory = KtPsiFactory(tmpFile) if (tmpFileImportList == null) { + val packageDirective = tmpFile.packageDirective tmpFile.addAfter(psiFactory.createNewLine(), packageDirective) tmpFile.addAfter(newImportList, tmpFile.packageDirective) } else { - val tmpFileImports = tmpFileImportList.imports - if (tmpFileImports.isEmpty()) { - tmpFileImportList.replace(newImportList) - } - else { - val lastImport = tmpFileImports.last() - newImportList.imports.forEach { - tmpFileImportList.addAfter(it, lastImport) - } - tmpFileImportList.addAfter(psiFactory.createNewLine(), lastImport) + newImportList.imports.forEach { + tmpFileImportList.add(psiFactory.createNewLine()) + tmpFileImportList.add(it) } + + tmpFileImportList.add(psiFactory.createNewLine()) } - tmpFile.addAfter(psiFactory.createNewLine(), packageDirective) } } diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective.kt b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective.kt new file mode 100644 index 00000000000..83353da6e2a --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective.kt @@ -0,0 +1,5 @@ +package foo + +fun main(args: Array) { + println() +} diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective.kt.after b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective.kt.after new file mode 100644 index 00000000000..dee0adbf270 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective.kt.after @@ -0,0 +1,6 @@ +package foo + +fun main(args: Array) { + 1 + 1 +println() +} diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective.kt.fragment b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective.kt.fragment new file mode 100644 index 00000000000..1a5a117eb38 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective.kt.fragment @@ -0,0 +1 @@ +1 + 1 \ No newline at end of file diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective2.kt b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective2.kt new file mode 100644 index 00000000000..83353da6e2a --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective2.kt @@ -0,0 +1,5 @@ +package foo + +fun main(args: Array) { + println() +} diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective2.kt.after b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective2.kt.after new file mode 100644 index 00000000000..2ab2b98941e --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective2.kt.after @@ -0,0 +1,8 @@ +package foo +import foo + + +fun main(args: Array) { + 1 + 1 +println() +} diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective2.kt.fragment b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective2.kt.fragment new file mode 100644 index 00000000000..42eb1636025 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective2.kt.fragment @@ -0,0 +1,3 @@ +import foo + +1 + 1 \ No newline at end of file diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective.kt b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective.kt new file mode 100644 index 00000000000..b9270fff1a2 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective.kt @@ -0,0 +1,3 @@ +fun main(args: Array) { + println() +} \ No newline at end of file diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective.kt.after b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective.kt.after new file mode 100644 index 00000000000..7d04eb04f40 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective.kt.after @@ -0,0 +1,4 @@ +fun main(args: Array) { + 1 + 1 +println() +} diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective.kt.fragment b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective.kt.fragment new file mode 100644 index 00000000000..1a5a117eb38 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective.kt.fragment @@ -0,0 +1 @@ +1 + 1 \ No newline at end of file diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective2.kt b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective2.kt new file mode 100644 index 00000000000..b9270fff1a2 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective2.kt @@ -0,0 +1,3 @@ +fun main(args: Array) { + println() +} \ No newline at end of file diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective2.kt.after b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective2.kt.after new file mode 100644 index 00000000000..8ceb31c56c0 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective2.kt.after @@ -0,0 +1,6 @@ + +import foo.* +fun main(args: Array) { + 1 + 1 +println() +} \ No newline at end of file diff --git a/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective2.kt.fragment b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective2.kt.fragment new file mode 100644 index 00000000000..6e1fb966b1a --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective2.kt.fragment @@ -0,0 +1,3 @@ +import foo.* + +1 + 1 \ No newline at end of file diff --git a/idea/testData/debugger/insertBeforeExtractFunction/manyImports.kt b/idea/testData/debugger/insertBeforeExtractFunction/manyImports.kt new file mode 100644 index 00000000000..29f56a31c73 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/manyImports.kt @@ -0,0 +1,8 @@ +package foo + +import a +import b + +fun main(args: Array) { + println() +} diff --git a/idea/testData/debugger/insertBeforeExtractFunction/manyImports.kt.after b/idea/testData/debugger/insertBeforeExtractFunction/manyImports.kt.after new file mode 100644 index 00000000000..0a6bb3f48f6 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/manyImports.kt.after @@ -0,0 +1,12 @@ +package foo + +import a +import b +import a +import b + + +fun main(args: Array) { + 1 + 1 +println() +} diff --git a/idea/testData/debugger/insertBeforeExtractFunction/manyImports.kt.fragment b/idea/testData/debugger/insertBeforeExtractFunction/manyImports.kt.fragment new file mode 100644 index 00000000000..7defc218d28 --- /dev/null +++ b/idea/testData/debugger/insertBeforeExtractFunction/manyImports.kt.fragment @@ -0,0 +1,4 @@ +import a +import b + +1 + 1 \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/AbstractBeforeExtractFunctionInsertionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/debugger/AbstractBeforeExtractFunctionInsertionTest.kt new file mode 100644 index 00000000000..1ada230aa3f --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/AbstractBeforeExtractFunctionInsertionTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.debugger + +import com.intellij.openapi.util.io.FileUtil +import com.intellij.testFramework.LightCodeInsightTestCase +import com.intellij.testFramework.LightPlatformCodeInsightTestCase +import org.jetbrains.kotlin.idea.core.refactoring.getLineNumber +import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory +import org.jetbrains.kotlin.idea.debugger.evaluate.addDebugExpressionIntoTmpFileForExtractFunction +import org.jetbrains.kotlin.psi.KtExpressionCodeFragment +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.test.KotlinTestUtils +import java.io.File + +abstract class AbstractBeforeExtractFunctionInsertionTest : LightCodeInsightTestCase() { + + fun doTest(path: String) { + configureByFile(path) + + val offset = LightPlatformCodeInsightTestCase.getEditor().caretModel.offset + val elementAt = KotlinCodeFragmentFactory.getContextElement(myFile.findElementAt(offset)) ?: throw AssertionError() + val line = elementAt.getLineNumber() + + val fragmentFile = KotlinTestUtils.createFile("${myFile.name}fragment.kt", FileUtil.loadFile(File(path + ".fragment"), true), getProject()) + + val imports = fragmentFile.importList?.text ?: "" + val allText = fragmentFile.text + val fragmentText = if (imports.isBlank()) allText else allText.substringAfter(imports, allText) + + val expressionList = addDebugExpressionIntoTmpFileForExtractFunction( + myFile as KtFile, + KtExpressionCodeFragment(getProject(), "fragment.kt", fragmentText, imports, elementAt), + line) + + KotlinTestUtils.assertEqualsToFile(File(path + ".after"), expressionList.first().containingFile.text) + } + + override fun getTestDataPath(): String { + return "" + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/BeforeExtractFunctionInsertionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/BeforeExtractFunctionInsertionTestGenerated.java new file mode 100644 index 00000000000..db44ceed0de --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/BeforeExtractFunctionInsertionTestGenerated.java @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.debugger; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/debugger/insertBeforeExtractFunction") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class BeforeExtractFunctionInsertionTestGenerated extends AbstractBeforeExtractFunctionInsertionTest { + public void testAllFilesPresentInInsertBeforeExtractFunction() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/debugger/insertBeforeExtractFunction"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("emptyImportDirective.kt") + public void testEmptyImportDirective() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective.kt"); + doTest(fileName); + } + + @TestMetadata("emptyImportDirective2.kt") + public void testEmptyImportDirective2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/insertBeforeExtractFunction/emptyImportDirective2.kt"); + doTest(fileName); + } + + @TestMetadata("emptyPackageDirective.kt") + public void testEmptyPackageDirective() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective.kt"); + doTest(fileName); + } + + @TestMetadata("emptyPackageDirective2.kt") + public void testEmptyPackageDirective2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/insertBeforeExtractFunction/emptyPackageDirective2.kt"); + doTest(fileName); + } + + @TestMetadata("manyImports.kt") + public void testManyImports() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/insertBeforeExtractFunction/manyImports.kt"); + doTest(fileName); + } +}