|
1 | 1 | package io.kotest.plugin.intellij.intentions
|
2 | 2 |
|
3 |
| -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction |
4 | 3 | import com.intellij.openapi.application.ApplicationManager
|
5 | 4 | import com.intellij.openapi.editor.Editor
|
| 5 | +import com.intellij.openapi.project.DumbAware |
6 | 6 | import com.intellij.openapi.project.Project
|
7 | 7 | import com.intellij.openapi.util.TextRange
|
8 | 8 | import com.intellij.psi.PsiDocumentManager
|
9 | 9 | import com.intellij.psi.PsiElement
|
10 |
| -import io.kotest.plugin.intellij.psi.isContainedInSpec |
11 | 10 | import org.jetbrains.kotlin.name.FqName
|
12 | 11 | import org.jetbrains.kotlin.psi.KtFile
|
13 | 12 | import org.jetbrains.kotlin.psi.KtPsiFactory
|
14 | 13 | import org.jetbrains.kotlin.resolve.ImportPath
|
15 | 14 |
|
16 |
| -internal var testMode = false |
17 |
| - |
18 |
| -abstract class SurroundSelectionWithFunctionIntention : PsiElementBaseIntentionAction() { |
| 15 | +abstract class SurroundSelectionWithFunctionIntention : TestSourceOnlyIntentionAction(), DumbAware { |
19 | 16 |
|
20 | 17 | override fun isAvailable(project: Project, editor: Editor?, element: PsiElement): Boolean {
|
21 |
| - if (ApplicationManager.getApplication().isDispatchThread && !testMode) { |
22 |
| - return false |
23 |
| - } |
24 |
| - return try { |
25 |
| - editor?.selectionModel?.hasSelection() == true && element.isContainedInSpec() |
26 |
| - } catch (e: Exception) { |
27 |
| - e.printStackTrace() |
28 |
| - false |
29 |
| - } |
| 18 | + return isTestSource(element) |
30 | 19 | }
|
31 | 20 |
|
32 | 21 | abstract val importFQN: FqName
|
33 | 22 | abstract val function: String
|
34 | 23 |
|
35 | 24 | override fun invoke(project: Project, editor: Editor?, element: PsiElement) {
|
| 25 | + if (editor == null) return |
| 26 | + addPsi(project, editor, element) |
| 27 | + } |
36 | 28 |
|
| 29 | + private fun addPsi(project: Project, editor: Editor, element: PsiElement) { |
37 | 30 | val docManager = PsiDocumentManager.getInstance(project)
|
38 | 31 | val ktfactory = KtPsiFactory(project)
|
39 | 32 |
|
40 | 33 | try {
|
41 | 34 |
|
42 |
| - val selection = editor?.selectionModel |
43 |
| - if (selection?.hasSelection() == true) { |
| 35 | + val selection = editor.selectionModel |
| 36 | + if (selection.hasSelection() == true) { |
44 | 37 |
|
45 |
| - val file = element.containingFile |
46 |
| - if (file is KtFile) { |
| 38 | + val file = element.containingFile |
| 39 | + if (file is KtFile) { |
47 | 40 |
|
48 |
| - val line1 = editor.document.getLineNumber(selection.selectionStart) |
49 |
| - val linen = editor.document.getLineNumber(selection.selectionEnd) |
| 41 | + val line1 = editor.document.getLineNumber(selection.selectionStart) |
| 42 | + val linen = editor.document.getLineNumber(selection.selectionEnd) |
50 | 43 |
|
51 |
| - // if our end position is column 0, then we've selected a full line - intellij wraps this onto the next line for some reason |
52 |
| - // val lineN0 = if (selection.selectionEndPosition?.column == 0) linen - 1 else linen |
| 44 | + // if our end position is column 0, then we've selected a full line - intellij wraps this onto the next line for some reason |
| 45 | + // val lineN0 = if (selection.selectionEndPosition?.column == 0) linen - 1 else linen |
53 | 46 |
|
54 |
| - // expand the text range to include the full lines of the selection |
55 |
| - val lineStart = editor.document.getLineStartOffset(line1) |
56 |
| - val lineEnd = editor.document.getLineEndOffset(linen) |
57 |
| - val lineRange = TextRange(lineStart, lineEnd) |
58 |
| - val text = editor.document.getText(lineRange) |
| 47 | + // expand the text range to include the full lines of the selection |
| 48 | + val lineStart = editor.document.getLineStartOffset(line1) |
| 49 | + val lineEnd = editor.document.getLineEndOffset(linen) |
| 50 | + val lineRange = TextRange(lineStart, lineEnd) |
| 51 | + val text = editor.document.getText(lineRange) |
59 | 52 |
|
60 |
| - // we need to work out how indented the first line was, so we can ident the function name the same amount |
61 |
| - val whitespacePrefix = text.takeWhile { it.isWhitespace() } |
| 53 | + // we need to work out how indented the first line was, so we can ident the function name the same amount |
| 54 | + val whitespacePrefix = text.takeWhile { it.isWhitespace() } |
62 | 55 |
|
63 |
| - // pad each of the original lines to include some extra padding as it will be further indented |
64 |
| - // 4 spaces seems to be what most kotlin files use but I like 2 :) |
65 |
| - val paddedStatements = text.split('\n').joinToString("\n") { " $it" } |
| 56 | + // pad each of the original lines to include some extra padding as it will be further indented |
| 57 | + // 4 spaces seems to be what most kotlin files use but I like 2 :) |
| 58 | + val paddedStatements = text.split('\n').joinToString("\n") { " $it" } |
66 | 59 |
|
67 |
| - // create a new string containing the wrapping function and the now-padded original statements |
68 |
| - val wrapped = "$whitespacePrefix$function {\n$paddedStatements\n$whitespacePrefix}" |
| 60 | + // create a new string containing the wrapping function and the now-padded original statements |
| 61 | + val wrapped = "$whitespacePrefix$function {\n$paddedStatements\n$whitespacePrefix}" |
69 | 62 |
|
70 |
| - // place the new block at the position of the original lines |
71 |
| - editor.document.replaceString(lineStart, lineEnd, wrapped) |
72 |
| - docManager.commitDocument(editor.document) |
| 63 | + // place the new block at the position of the original lines |
| 64 | + editor.document.replaceString(lineStart, lineEnd, wrapped) |
| 65 | + docManager.commitDocument(editor.document) |
73 | 66 |
|
74 |
| - // best add the import if needed for the function |
75 |
| - val importPath = ImportPath(importFQN, false) |
76 |
| - val list = file.importList |
77 |
| - if (list != null) { |
78 |
| - if (list.imports.none { it.importPath == importPath }) { |
79 |
| - val imp = ktfactory.createImportDirective(importPath) |
80 |
| - list.add(imp) |
81 |
| - } |
82 |
| - } |
| 67 | + // best add the import if needed for the function |
| 68 | + val importPath = ImportPath(importFQN, false) |
| 69 | + val list = file.importList |
| 70 | + if (list != null) { |
| 71 | + if (list.imports.none { it.importPath == importPath }) { |
| 72 | + val imp = ktfactory.createImportDirective(importPath) |
| 73 | + list.add(imp) |
| 74 | + } |
| 75 | + } |
83 | 76 |
|
84 |
| - docManager.doPostponedOperationsAndUnblockDocument(editor.document) |
85 |
| - } |
| 77 | + docManager.doPostponedOperationsAndUnblockDocument(editor.document) |
| 78 | + } |
| 79 | + } |
| 80 | + } catch (e: Exception) { |
| 81 | + e.printStackTrace() |
86 | 82 | }
|
87 |
| - } catch (e: Exception) { |
88 |
| - e.printStackTrace() |
89 |
| - } |
90 |
| - } |
| 83 | + } |
91 | 84 | }
|
0 commit comments