Unit Test Tooling: Implement "Create Test" action
#KT-6472 In Progress
This commit is contained in:
@@ -17,8 +17,9 @@
|
||||
package org.jetbrains.kotlin.idea.util.application
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
import com.intellij.openapi.project.DumbService
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
public fun runReadAction<T>(action: () -> T): T {
|
||||
return ApplicationManager.getApplication().runReadAction<T>(action)
|
||||
@@ -32,13 +33,20 @@ public fun Project.executeWriteCommand(name: String, command: () -> Unit) {
|
||||
CommandProcessor.getInstance().executeCommand(this, { runWriteAction(command) }, name, null)
|
||||
}
|
||||
|
||||
public fun Project.executeCommand(name: String, groupId: Any? = null, command: () -> Unit) {
|
||||
CommandProcessor.getInstance().executeCommand(this, command, name, groupId)
|
||||
public fun <T> Project.executeWriteCommand(name: String, groupId: Any? = null, command: () -> T): T {
|
||||
return executeCommand<T>(name, groupId) { runWriteAction(command) }
|
||||
}
|
||||
|
||||
public fun <T> Project.executeWriteCommand(name: String, groupId: Any? = null, command: () -> T): T {
|
||||
public fun <T> Project.executeCommand(name: String, groupId: Any? = null, command: () -> T): T {
|
||||
var result: T = null as T
|
||||
CommandProcessor.getInstance().executeCommand(this, { result = runWriteAction(command) }, name, groupId)
|
||||
CommandProcessor.getInstance().executeCommand(this, { result = command() }, name, groupId)
|
||||
@Suppress("USELESS_CAST")
|
||||
return result as T
|
||||
}
|
||||
|
||||
public fun <T> Project.runWithAlternativeResolveEnabled(action: () -> T): T {
|
||||
var result: T = null as T
|
||||
DumbService.getInstance(this).withAlternativeResolveEnabled { result = action() }
|
||||
@Suppress("USELESS_CAST")
|
||||
return result as T
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class Foo {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class FooTest : TestCase {
|
||||
fun testFoo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<spot>class Foo</spot> {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention generates a test case for the selected class. The generated class contains skeleton test functions for the chosen public functions.
|
||||
</body>
|
||||
</html>
|
||||
@@ -1062,6 +1062,11 @@
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.kotlin.idea.testIntegration.KotlinCreateTestIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<localInspection implementationClass="org.jetbrains.kotlin.idea.intentions.DeprecatedCallableAddReplaceWithInspection"
|
||||
displayName="Add 'replaceWith' argument to 'deprecated' annotation"
|
||||
groupName="Kotlin"
|
||||
|
||||
@@ -32,67 +32,104 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.openapi.vfs.VirtualFileVisitor
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.toPsiFile
|
||||
import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices
|
||||
import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.j2k.ConverterSettings
|
||||
import org.jetbrains.kotlin.j2k.JavaToKotlinConverter
|
||||
import org.jetbrains.kotlin.psi.JetFile
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.ArrayList
|
||||
|
||||
public class JavaToKotlinAction : AnAction() {
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
ApplicationManager.getApplication().saveAll()
|
||||
companion object {
|
||||
private fun uniqueKotlinFileName(javaFile: VirtualFile): String {
|
||||
val ioFile = File(javaFile.getPath().replace('/', File.separatorChar))
|
||||
|
||||
var i = 0
|
||||
while (true) {
|
||||
val fileName = javaFile.getNameWithoutExtension() + (if (i > 0) i else "") + ".kt"
|
||||
if (!ioFile.resolveSibling(fileName).exists()) return fileName
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveResults(javaFiles: List<PsiJavaFile>, convertedTexts: List<String>): List<VirtualFile> {
|
||||
val result = ArrayList<VirtualFile>()
|
||||
for ((psiFile, text) in javaFiles.zip(convertedTexts)) {
|
||||
val virtualFile = psiFile.getVirtualFile()
|
||||
val fileName = uniqueKotlinFileName(virtualFile)
|
||||
try {
|
||||
virtualFile.rename(this, fileName)
|
||||
virtualFile.setBinaryContent(CharsetToolkit.getUtf8Bytes(text))
|
||||
result.add(virtualFile)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
MessagesEx.error(psiFile.getProject(), e.getMessage()).showLater()
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
fun convertFiles(javaFiles: List<PsiJavaFile>, project: Project, enableExternalCodeProcessing: Boolean = true): List<JetFile> {
|
||||
ApplicationManager.getApplication().saveAll()
|
||||
|
||||
var converterResult: JavaToKotlinConverter.FilesResult? = null
|
||||
fun convert() {
|
||||
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaJavaToKotlinServices)
|
||||
converterResult = converter.filesToKotlin(javaFiles, J2kPostProcessor(formatCode = true), ProgressManager.getInstance().getProgressIndicator())
|
||||
}
|
||||
|
||||
val title = "Convert Java to Kotlin"
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
{
|
||||
runReadAction(::convert)
|
||||
},
|
||||
title,
|
||||
true,
|
||||
project)) return emptyList()
|
||||
|
||||
|
||||
var externalCodeUpdate: (() -> Unit)? = null
|
||||
|
||||
if (enableExternalCodeProcessing && converterResult!!.externalCodeProcessing != null) {
|
||||
val question = "Some code in the rest of your project may require corrections after performing this conversion. Do you want to find such code and correct it too?"
|
||||
if (Messages.showOkCancelDialog(project, question, title, Messages.getQuestionIcon()) == Messages.OK) {
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
{
|
||||
runReadAction {
|
||||
externalCodeUpdate = converterResult!!.externalCodeProcessing!!.prepareWriteOperation(ProgressManager.getInstance().getProgressIndicator())
|
||||
}
|
||||
},
|
||||
title,
|
||||
true,
|
||||
project)
|
||||
}
|
||||
}
|
||||
|
||||
return project.executeWriteCommand("Convert files from Java to Kotlin", null) {
|
||||
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project)
|
||||
|
||||
val newFiles = saveResults(javaFiles, converterResult!!.results)
|
||||
|
||||
externalCodeUpdate?.invoke()
|
||||
|
||||
newFiles.singleOrNull()?.let {
|
||||
FileEditorManager.getInstance(project).openFile(it, true)
|
||||
}
|
||||
|
||||
newFiles.map { it.toPsiFile(project) as JetFile }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun actionPerformed(e: AnActionEvent) {
|
||||
val javaFiles = selectedJavaFiles(e).toList()
|
||||
val project = CommonDataKeys.PROJECT.getData(e.getDataContext())!!
|
||||
|
||||
var converterResult: JavaToKotlinConverter.FilesResult? = null
|
||||
fun convert() {
|
||||
val converter = JavaToKotlinConverter(project, ConverterSettings.defaultSettings, IdeaJavaToKotlinServices)
|
||||
converterResult = converter.filesToKotlin(javaFiles, J2kPostProcessor(formatCode = true), ProgressManager.getInstance().getProgressIndicator())
|
||||
}
|
||||
|
||||
val title = "Convert Java to Kotlin"
|
||||
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
{
|
||||
runReadAction(::convert)
|
||||
},
|
||||
title,
|
||||
true,
|
||||
project)) return
|
||||
|
||||
|
||||
var externalCodeUpdate: (() -> Unit)? = null
|
||||
|
||||
if (converterResult!!.externalCodeProcessing != null) {
|
||||
val question = "Some code in the rest of your project may require corrections after performing this conversion. Do you want to find such code and correct it too?"
|
||||
if (Messages.showOkCancelDialog(project, question, title, Messages.getQuestionIcon()) == Messages.OK) {
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
{
|
||||
runReadAction {
|
||||
externalCodeUpdate = converterResult!!.externalCodeProcessing!!.prepareWriteOperation(ProgressManager.getInstance().getProgressIndicator())
|
||||
}
|
||||
},
|
||||
title,
|
||||
true,
|
||||
project)
|
||||
}
|
||||
}
|
||||
|
||||
project.executeWriteCommand("Convert files from Java to Kotlin") {
|
||||
CommandProcessor.getInstance().markCurrentCommandAsGlobal(project)
|
||||
|
||||
val newFiles = saveResults(javaFiles, converterResult!!.results)
|
||||
|
||||
externalCodeUpdate?.invoke()
|
||||
|
||||
newFiles.singleOrNull()?.let {
|
||||
FileEditorManager.getInstance(project).openFile(it, true)
|
||||
}
|
||||
}
|
||||
convertFiles(javaFiles, project)
|
||||
}
|
||||
|
||||
override fun update(e: AnActionEvent) {
|
||||
@@ -126,32 +163,4 @@ public class JavaToKotlinAction : AnAction() {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun saveResults(javaFiles: List<PsiJavaFile>, convertedTexts: List<String>): List<VirtualFile> {
|
||||
val result = ArrayList<VirtualFile>()
|
||||
for ((psiFile, text) in javaFiles.zip(convertedTexts)) {
|
||||
val virtualFile = psiFile.getVirtualFile()
|
||||
val fileName = uniqueKotlinFileName(virtualFile)
|
||||
try {
|
||||
virtualFile.rename(this, fileName)
|
||||
virtualFile.setBinaryContent(CharsetToolkit.getUtf8Bytes(text))
|
||||
result.add(virtualFile)
|
||||
}
|
||||
catch (e: IOException) {
|
||||
MessagesEx.error(psiFile.getProject(), e.getMessage()).showLater()
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun uniqueKotlinFileName(javaFile: VirtualFile): String {
|
||||
val ioFile = File(javaFile.getPath().replace('/', File.separatorChar))
|
||||
|
||||
var i = 0
|
||||
while (true) {
|
||||
val fileName = javaFile.getNameWithoutExtension() + (if (i > 0) i else "") + ".kt"
|
||||
if (!ioFile.resolveSibling(fileName).exists()) return fileName
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-10
@@ -21,14 +21,12 @@ import com.intellij.codeInsight.generation.actions.GenerateActionPopupTemplateIn
|
||||
import com.intellij.codeInsight.hint.HintManager
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager
|
||||
import com.intellij.ide.fileTemplates.impl.AllFileTemplatesConfigurable
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.actionSystem.AnAction
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||
import com.intellij.openapi.actionSystem.DataContext
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.InputValidator
|
||||
import com.intellij.openapi.ui.Messages
|
||||
@@ -42,7 +40,6 @@ import com.intellij.testIntegration.TestFramework
|
||||
import com.intellij.testIntegration.TestIntegrationUtils.MethodKind
|
||||
import com.intellij.ui.components.JBList
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
@@ -52,6 +49,7 @@ import org.jetbrains.kotlin.idea.core.overrideImplement.generateUnsupportedOrSup
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.j2k
|
||||
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.setupEditorSelection
|
||||
import org.jetbrains.kotlin.idea.quickfix.generateMember
|
||||
import org.jetbrains.kotlin.idea.testIntegration.findSuitableFrameworks
|
||||
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||
@@ -69,13 +67,6 @@ abstract class KotlinGenerateTestSupportActionBase(
|
||||
return elementAtCaret.parentsWithSelf.filterIsInstance<JetClassOrObject>().firstOrNull { !it.isLocal() }
|
||||
}
|
||||
|
||||
private fun findSuitableFrameworks(klass: JetClassOrObject): List<TestFramework> {
|
||||
val lightClass = klass.toLightClass() ?: return emptyList()
|
||||
val frameworks = Extensions.getExtensions(TestFramework.EXTENSION_NAME).filter { it.language == JavaLanguage.INSTANCE }
|
||||
return frameworks.firstOrNull { it.isTestClass(lightClass) }?.let { listOf(it) }
|
||||
?: frameworks.filterTo(SmartList<TestFramework>()) { it.isPotentialTestClass(lightClass) }
|
||||
}
|
||||
|
||||
private fun chooseAndPerform(editor: Editor, frameworks: List<TestFramework>, consumer: (TestFramework) -> Unit) {
|
||||
frameworks.ifEmpty { return }
|
||||
frameworks.singleOrNull()?.let { return consumer(it) }
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.testIntegration
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiPackage
|
||||
import com.intellij.testIntegration.createTest.CreateTestDialog
|
||||
|
||||
class KotlinCreateTestDialog(project: Project,
|
||||
title: String,
|
||||
targetClass: PsiClass?,
|
||||
targetPackage: PsiPackage?,
|
||||
targetModule: Module) : CreateTestDialog(project, title, targetClass, targetPackage, targetModule) {
|
||||
public var explicitClassName: String? = null
|
||||
|
||||
override fun getClassName() = explicitClassName ?: super.getClassName()
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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.testIntegration
|
||||
|
||||
import com.intellij.CommonBundle
|
||||
import com.intellij.codeInsight.CodeInsightBundle
|
||||
import com.intellij.codeInsight.FileModificationService
|
||||
import com.intellij.codeInsight.navigation.NavigationUtil
|
||||
import com.intellij.ide.util.PropertiesComponent
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.module.ModuleUtilCore
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.search.GlobalSearchScopesCore
|
||||
import com.intellij.testIntegration.createTest.CreateTestAction
|
||||
import com.intellij.testIntegration.createTest.TestGenerators
|
||||
import org.jetbrains.kotlin.asJava.KotlinLightClass
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.idea.actions.JavaToKotlinAction
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||
import org.jetbrains.kotlin.idea.core.getPackage
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.j2k
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.toPsiDirectory
|
||||
import org.jetbrains.kotlin.idea.intentions.JetSelfTargetingRangeIntention
|
||||
import org.jetbrains.kotlin.idea.util.application.executeCommand
|
||||
import org.jetbrains.kotlin.idea.util.application.runWithAlternativeResolveEnabled
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.psi.JetClass
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||
import org.jetbrains.kotlin.psi.JetEnumEntry
|
||||
import org.jetbrains.kotlin.psi.JetNamedFunction
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
|
||||
import java.util.*
|
||||
|
||||
class KotlinCreateTestIntention : JetSelfTargetingRangeIntention<JetClassOrObject>(
|
||||
JetClassOrObject::class.java,
|
||||
CodeInsightBundle.message("intention.create.test")
|
||||
) {
|
||||
override fun applicabilityRange(element: JetClassOrObject): TextRange? {
|
||||
if (element.isLocal()) return null
|
||||
if (element is JetEnumEntry) return null
|
||||
if (element is JetClass && (element.isAnnotation() || element.isInterface())) return null
|
||||
if (ModuleUtilCore.findModuleForPsiElement(element) == null) return null
|
||||
if (element.resolveToDescriptorIfAny() == null) return null
|
||||
|
||||
return TextRange(
|
||||
element.startOffset,
|
||||
element.getDelegationSpecifierList()?.startOffset ?: element.getBody()?.startOffset ?: element.endOffset
|
||||
)
|
||||
}
|
||||
|
||||
override fun applyTo(element: JetClassOrObject, editor: Editor) {
|
||||
object : CreateTestAction() {
|
||||
// Based on the com.intellij.testIntegration.createTest.JavaTestGenerator.createTestClass()
|
||||
private fun findTestClass(targetDirectory: PsiDirectory, className: String): PsiClass? {
|
||||
val psiPackage = targetDirectory.getPackage() ?: return null
|
||||
val scope = GlobalSearchScopesCore.directoryScope(targetDirectory, false)
|
||||
val klass = psiPackage.findClassByShortName(className, scope).firstOrNull() ?: return null
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(klass)) return null
|
||||
return klass
|
||||
}
|
||||
|
||||
private fun getTempJavaClassName(project: Project, kotlinFile: VirtualFile): String {
|
||||
val baseName = kotlinFile.nameWithoutExtension
|
||||
val psiDir = kotlinFile.parent!!.toPsiDirectory(project)!!
|
||||
return sequence(0) { it + 1 }
|
||||
.map { "$baseName$it" }
|
||||
.first { psiDir.findFile("$it.java") == null && findTestClass(psiDir, it) == null }
|
||||
}
|
||||
|
||||
// Based on the com.intellij.testIntegration.createTest.CreateTestAction.CreateTestAction.invoke()
|
||||
override fun invoke(project: Project, editor: Editor?, element: PsiElement) {
|
||||
val srcModule = ModuleUtilCore.findModuleForPsiElement(element) ?: return
|
||||
val propertiesComponent = PropertiesComponent.getInstance()
|
||||
val testFolders = HashSet<VirtualFile>()
|
||||
CreateTestAction.checkForTestRoots(srcModule, testFolders)
|
||||
if (testFolders.isEmpty() && !propertiesComponent.getBoolean("create.test.in.the.same.root")) {
|
||||
if (Messages.showOkCancelDialog(
|
||||
project,
|
||||
"Create test in the same source root?",
|
||||
"No Test Roots Found",
|
||||
Messages.getQuestionIcon()) != Messages.OK) return
|
||||
|
||||
propertiesComponent.setValue("create.test.in.the.same.root", true)
|
||||
}
|
||||
|
||||
val srcClass = CreateTestAction.getContainingClass(element) ?: return
|
||||
|
||||
val srcDir = element.containingFile.containingDirectory
|
||||
val srcPackage = JavaDirectoryService.getInstance().getPackage(srcDir)
|
||||
|
||||
val dialog = KotlinCreateTestDialog(project, text, srcClass, srcPackage, srcModule)
|
||||
if (!dialog.showAndGet()) return
|
||||
|
||||
val existingClass = (findTestClass(dialog.targetDirectory, dialog.className) as? KotlinLightClass)?.getOrigin()
|
||||
if (existingClass != null) {
|
||||
// TODO: Override dialog method when it becomes protected
|
||||
val answer = Messages.showYesNoDialog(
|
||||
project,
|
||||
"Kotlin class '${existingClass.name}' already exists. Do you want to update it?",
|
||||
CommonBundle.getErrorTitle(),
|
||||
"Rewrite",
|
||||
"Cancel",
|
||||
Messages.getErrorIcon()
|
||||
)
|
||||
if (answer == Messages.NO) return
|
||||
}
|
||||
|
||||
val generatedClass = project.executeCommand(CodeInsightBundle.message("intention.create.test"), this) {
|
||||
val generator = TestGenerators.INSTANCE.forLanguage(dialog.selectedTestFrameworkDescriptor.language)
|
||||
project.runWithAlternativeResolveEnabled {
|
||||
if (existingClass != null) {
|
||||
dialog.explicitClassName = getTempJavaClassName(project, existingClass.containingFile.virtualFile)
|
||||
}
|
||||
generator.generateTest(project, dialog)
|
||||
}
|
||||
} as? PsiClass ?: return
|
||||
|
||||
val generatedFile = generatedClass.containingFile as? PsiJavaFile ?: return
|
||||
|
||||
if (generatedClass.language == JavaLanguage.INSTANCE) {
|
||||
project.executeCommand("Convert class '${generatedClass.name}' to Kotlin", this) {
|
||||
runWriteAction {
|
||||
generatedClass.methods.forEach { it.throwsList.referenceElements.forEach { it.delete() } }
|
||||
}
|
||||
|
||||
if (existingClass != null) {
|
||||
runWriteAction {
|
||||
val existingMethodNames = existingClass
|
||||
.declarations
|
||||
.filterIsInstance<JetNamedFunction>()
|
||||
.mapTo(HashSet()) { it.name }
|
||||
generatedClass
|
||||
.methods
|
||||
.filter { it.name !in existingMethodNames }
|
||||
.forEach { it.j2k()?.let { existingClass.addDeclaration(it) } }
|
||||
generatedClass.delete()
|
||||
}
|
||||
NavigationUtil.activateFileWithPsiElement(existingClass)
|
||||
}
|
||||
else {
|
||||
JavaToKotlinAction.convertFiles(generatedFile.singletonList(), project, false).singleOrNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.invoke(element.project, editor, element.toLightClass()!!)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.testIntegration
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.testIntegration.TestFramework
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.asJava.toLightClass
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||
|
||||
public fun findSuitableFrameworks(klass: JetClassOrObject): List<TestFramework> {
|
||||
val lightClass = klass.toLightClass() ?: return emptyList()
|
||||
val frameworks = Extensions.getExtensions(TestFramework.EXTENSION_NAME).filter { it.language == JavaLanguage.INSTANCE }
|
||||
return frameworks.firstOrNull { it.isTestClass(lightClass) }?.let { listOf(it) }
|
||||
?: frameworks.filterTo(SmartList<TestFramework>()) { it.isPotentialTestClass(lightClass) }
|
||||
}
|
||||
idea/testData/quickfix/createFromUsage/createClass/delegationSpecifier/classDelegatorToSuperclass.kt
Vendored
+1
@@ -1,5 +1,6 @@
|
||||
// "Create class 'A'" "false"
|
||||
// ACTION: Create interface 'A'
|
||||
// ACTION: Create Test
|
||||
// ERROR: Unresolved reference: A
|
||||
package p
|
||||
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
// "class org.jetbrains.kotlin.idea.quickfix.AddOpenModifierToClassDeclarationFix" "false"
|
||||
// ERROR: This type is final, so it cannot be inherited from
|
||||
// ACTION: Create Test
|
||||
import testPackage.*
|
||||
|
||||
class foo : <caret>JavaClass() {}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// "Cast expression 'Foo<Number>()' to 'Foo<Int>'" "false"
|
||||
// ACTION: Create Test
|
||||
// ERROR: <html>Type mismatch.<table><tr><td>Required:</td><td>Foo<kotlin.Int></td></tr><tr><td>Found:</td><td>Foo<kotlin.Number></td></tr></table></html>
|
||||
class Foo<T>
|
||||
|
||||
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
// "Remove 'val' from parameter" "false"
|
||||
// ACTION: Make internal
|
||||
// ACTION: Make private
|
||||
// ACTION: Create Test
|
||||
class C(<caret>val x: String) {
|
||||
}
|
||||
Reference in New Issue
Block a user