diff --git a/src/IC-242/kotlin/io/kotest/plugin/intellij/psi/superClasses.kt b/src/IC-242/kotlin/io/kotest/plugin/intellij/psi/superClasses.kt index e05bc35f..cebbe390 100644 --- a/src/IC-242/kotlin/io/kotest/plugin/intellij/psi/superClasses.kt +++ b/src/IC-242/kotlin/io/kotest/plugin/intellij/psi/superClasses.kt @@ -11,21 +11,15 @@ import org.jetbrains.kotlin.psi.KtClassOrObject /** * Recursively returns the list of classes and interfaces extended or implemented by the class. */ -@OptIn(KaAllowAnalysisOnEdt::class) fun KtClassOrObject.getAllSuperClasses(): List { return superTypeListEntries.mapNotNull { it.typeReference } .flatMap { ref -> - // SurroundSelectionWithFunctionIntention.isAvailable is called in EDT before the intention is applied - // unfortunately API to avoid this was introduced in 23.2 only - // this we need to move intentions to the facade or accept EDT here until 23.2- are still supported - allowAnalysisOnEdt { - analyze(this) { - val kaType = ref.type - val superTypes = (kaType.allSupertypes(false) + kaType).toList() - superTypes.mapNotNull { - val classId = it.symbol?.classId?.takeIf { id -> id != StandardClassIds.Any } - classId?.asSingleFqName() - } + analyze(this) { + val kaType = ref.type + val superTypes = (kaType.allSupertypes(false) + kaType).toList() + superTypes.mapNotNull { + val classId = it.symbol?.classId?.takeIf { id -> id != StandardClassIds.Any } + classId?.asSingleFqName() } } } diff --git a/src/IC-243/kotlin/io/kotest/plugin/intellij/psi/superClasses.kt b/src/IC-243/kotlin/io/kotest/plugin/intellij/psi/superClasses.kt index e05bc35f..bc0259a5 100644 --- a/src/IC-243/kotlin/io/kotest/plugin/intellij/psi/superClasses.kt +++ b/src/IC-243/kotlin/io/kotest/plugin/intellij/psi/superClasses.kt @@ -1,8 +1,6 @@ package io.kotest.plugin.intellij.psi import org.jetbrains.kotlin.analysis.api.analyze -import org.jetbrains.kotlin.analysis.api.permissions.KaAllowAnalysisOnEdt -import org.jetbrains.kotlin.analysis.api.permissions.allowAnalysisOnEdt import org.jetbrains.kotlin.analysis.api.types.symbol import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.StandardClassIds @@ -11,21 +9,15 @@ import org.jetbrains.kotlin.psi.KtClassOrObject /** * Recursively returns the list of classes and interfaces extended or implemented by the class. */ -@OptIn(KaAllowAnalysisOnEdt::class) fun KtClassOrObject.getAllSuperClasses(): List { return superTypeListEntries.mapNotNull { it.typeReference } .flatMap { ref -> - // SurroundSelectionWithFunctionIntention.isAvailable is called in EDT before the intention is applied - // unfortunately API to avoid this was introduced in 23.2 only - // this we need to move intentions to the facade or accept EDT here until 23.2- are still supported - allowAnalysisOnEdt { - analyze(this) { - val kaType = ref.type - val superTypes = (kaType.allSupertypes(false) + kaType).toList() - superTypes.mapNotNull { - val classId = it.symbol?.classId?.takeIf { id -> id != StandardClassIds.Any } - classId?.asSingleFqName() - } + analyze(this) { + val kaType = ref.type + val superTypes = (kaType.allSupertypes(false) + kaType).toList() + superTypes.mapNotNull { + val classId = it.symbol?.classId?.takeIf { id -> id != StandardClassIds.Any } + classId?.asSingleFqName() } } } diff --git a/src/main/kotlin/io/kotest/plugin/intellij/intentions/SurroundSelectionWithFunctionIntention.kt b/src/main/kotlin/io/kotest/plugin/intellij/intentions/SurroundSelectionWithFunctionIntention.kt index 849e2370..e64b18b9 100644 --- a/src/main/kotlin/io/kotest/plugin/intellij/intentions/SurroundSelectionWithFunctionIntention.kt +++ b/src/main/kotlin/io/kotest/plugin/intellij/intentions/SurroundSelectionWithFunctionIntention.kt @@ -6,7 +6,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement -import io.kotest.plugin.intellij.psi.isContainedInSpec +import io.kotest.plugin.intellij.psi.isTestFile import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtPsiFactory @@ -15,12 +15,12 @@ import org.jetbrains.kotlin.resolve.ImportPath abstract class SurroundSelectionWithFunctionIntention : PsiElementBaseIntentionAction() { override fun isAvailable(project: Project, editor: Editor?, element: PsiElement): Boolean { - return try { - editor?.selectionModel?.hasSelection() == true && element.isContainedInSpec() - } catch (e: Exception) { - e.printStackTrace() - false - } + if (editor == null) return false + return editor.virtualFile.isTestFile(project) + } + + override fun startInWriteAction(): Boolean { + return super.startInWriteAction() } abstract val importFQN: FqName @@ -33,53 +33,53 @@ abstract class SurroundSelectionWithFunctionIntention : PsiElementBaseIntentionA try { - val selection = editor?.selectionModel - if (selection?.hasSelection() == true) { + val selection = editor?.selectionModel + if (selection?.hasSelection() == true) { - val file = element.containingFile - if (file is KtFile) { + val file = element.containingFile + if (file is KtFile) { - val line1 = editor.document.getLineNumber(selection.selectionStart) - val linen = editor.document.getLineNumber(selection.selectionEnd) + val line1 = editor.document.getLineNumber(selection.selectionStart) + val linen = editor.document.getLineNumber(selection.selectionEnd) - // if our end position is column 0, then we've selected a full line - intellij wraps this onto the next line for some reason - // val lineN0 = if (selection.selectionEndPosition?.column == 0) linen - 1 else linen + // if our end position is column 0, then we've selected a full line - intellij wraps this onto the next line for some reason + // val lineN0 = if (selection.selectionEndPosition?.column == 0) linen - 1 else linen - // expand the text range to include the full lines of the selection - val lineStart = editor.document.getLineStartOffset(line1) - val lineEnd = editor.document.getLineEndOffset(linen) - val lineRange = TextRange(lineStart, lineEnd) - val text = editor.document.getText(lineRange) + // expand the text range to include the full lines of the selection + val lineStart = editor.document.getLineStartOffset(line1) + val lineEnd = editor.document.getLineEndOffset(linen) + val lineRange = TextRange(lineStart, lineEnd) + val text = editor.document.getText(lineRange) - // we need to work out how indented the first line was, so we can ident the function name the same amount - val whitespacePrefix = text.takeWhile { it.isWhitespace() } + // we need to work out how indented the first line was, so we can ident the function name the same amount + val whitespacePrefix = text.takeWhile { it.isWhitespace() } - // pad each of the original lines to include some extra padding as it will be further indented - // 4 spaces seems to be what most kotlin files use but I like 2 :) - val paddedStatements = text.split('\n').joinToString("\n") { " $it" } + // pad each of the original lines to include some extra padding as it will be further indented + // 4 spaces seems to be what most kotlin files use but I like 2 :) + val paddedStatements = text.split('\n').joinToString("\n") { " $it" } - // create a new string containing the wrapping function and the now-padded original statements - val wrapped = "$whitespacePrefix$function {\n$paddedStatements\n$whitespacePrefix}" + // create a new string containing the wrapping function and the now-padded original statements + val wrapped = "$whitespacePrefix$function {\n$paddedStatements\n$whitespacePrefix}" - // place the new block at the position of the original lines - editor.document.replaceString(lineStart, lineEnd, wrapped) - docManager.commitDocument(editor.document) + // place the new block at the position of the original lines + editor.document.replaceString(lineStart, lineEnd, wrapped) + docManager.commitDocument(editor.document) - // best add the import if needed for the function - val importPath = ImportPath(importFQN, false) - val list = file.importList - if (list != null) { - if (list.imports.none { it.importPath == importPath }) { - val imp = ktfactory.createImportDirective(importPath) - list.add(imp) - } - } + // best add the import if needed for the function + val importPath = ImportPath(importFQN, false) + val list = file.importList + if (list != null) { + if (list.imports.none { it.importPath == importPath }) { + val imp = ktfactory.createImportDirective(importPath) + list.add(imp) + } + } - docManager.doPostponedOperationsAndUnblockDocument(editor.document) - } + docManager.doPostponedOperationsAndUnblockDocument(editor.document) + } + } + } catch (e: Exception) { + e.printStackTrace() } - } catch (e: Exception) { - e.printStackTrace() - } - } + } } diff --git a/src/main/kotlin/io/kotest/plugin/intellij/psi/specs.kt b/src/main/kotlin/io/kotest/plugin/intellij/psi/specs.kt index 7579c499..49d5f87e 100644 --- a/src/main/kotlin/io/kotest/plugin/intellij/psi/specs.kt +++ b/src/main/kotlin/io/kotest/plugin/intellij/psi/specs.kt @@ -40,7 +40,7 @@ fun KtClassOrObject.isSpec(): Boolean { */ fun PsiElement.isSpec(): Boolean = when (this) { is KtUltraLightClass -> kotlinOrigin.isSpec() - is KtLightClass -> kotlinOrigin?.isSpec() ?: false + is KtLightClass -> kotlinOrigin?.isSpec() == true is KtClassOrObject -> isSpec() else -> false }