Skip to content

Commit

Permalink
Simplify superclasses
Browse files Browse the repository at this point in the history
  • Loading branch information
sksamuel committed Dec 24, 2024
1 parent bc7f3ea commit 82ecce5
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 72 deletions.
18 changes: 6 additions & 12 deletions src/IC-242/kotlin/io/kotest/plugin/intellij/psi/superClasses.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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<FqName> {
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()
}
}
}
Expand Down
20 changes: 6 additions & 14 deletions src/IC-243/kotlin/io/kotest/plugin/intellij/psi/superClasses.kt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<FqName> {
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()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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()
}
}
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/io/kotest/plugin/intellij/psi/specs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit 82ecce5

Please sign in to comment.