|
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