override fun performAction()

in src/com/intellij/idea/plugin/hybris/impex/actions/ImpExTableSplitVerticallyAction.kt [64:194]


    override fun performAction(project: Project, editor: Editor, psiFile: PsiFile, element: PsiElement) {
        currentThreadCoroutineScope().launch {
            val headerParameter =
                readAction {
                    if (!psiFile.isValid) return@readAction null

                    when (element) {
                        is ImpexFullHeaderParameter -> element
                        is ImpexValueGroup -> element.fullHeaderParameter
                            ?: return@readAction null

                        else -> return@readAction null
                    }
                } ?: return@launch

            val headerLine = readAction { headerParameter.headerLine } ?: return@launch

            val columnNumber = readAction { headerParameter.columnNumber }
            val headerParameters = readAction { headerLine.fullHeaderParameterList.size }

            // collect numbers of all unique columns
            val uniqueColumns = readAction {
                headerLine.uniqueFullHeaderParameters
                    .map { it.columnNumber }
            }

            // calculate table range
            val tableRange = readAction { headerLine.tableRange }

            // let's start cloning! left
            val cloneTableLeft = readAction {
                ImpExElementFactory.createFile(
                    project,
                    psiFile.text.substring(tableRange.startOffset, tableRange.endOffset)
                )
            }

            // grab header lines from both cloned future left and right tables
            val cloneLeftHeaderLine = readAction { cloneTableLeft.childrenOfType<ImpexHeaderLine>().firstOrNull() }
                ?: return@launch
            val valueLines = readAction { cloneLeftHeaderLine.valueLines }

            // before the actual split, we have to ensure that we have enough value groups
            val addValueGroups = valueLines.associateWith {
                val valueGroups = readAction { it.valueGroupList }
                readAction { headerParameters - valueGroups.size }
            }
                .filter { it.value > 0 }

            withContext(Dispatchers.EDT) {
                PostprocessReformattingAspect.getInstance(project).disablePostprocessFormattingInside {
                    runWithModalProgressBlocking(project, "Adding missing value groups before splitting") {
                        addValueGroups.entries.forEachWithProgress {
                            WriteCommandAction.runWriteCommandAction(
                                project, commandName, groupID,
                                { it.key.addValueGroups(it.value) },
                                psiFile
                            )
                        }
                    }
                }
            }

            // and clone right
            val cloneTableRight = readAction { cloneTableLeft.copy() }
            val cloneRightHeaderLine = readAction { cloneTableRight.childrenOfType<ImpexHeaderLine>().firstOrNull() }
                ?: return@launch

            val elementsToRemove = mutableListOf<PsiElement>()

            // before deletion of the header params, we have to remove value groups
            // delete value groups from the left table
            collectValueGroups(cloneLeftHeaderLine) {
                it >= columnNumber && !uniqueColumns.contains(it)
            }.also { elementsToRemove.addAll(it) }

            // and delete value groups from the right table
            collectValueGroups(cloneRightHeaderLine) {
                it < columnNumber && !uniqueColumns.contains(it)
            }.also { elementsToRemove.addAll(it) }

            // delete header param from the left table
            collectHeaderParams(cloneLeftHeaderLine) {
                it >= columnNumber && !uniqueColumns.contains(it)
            }.also { elementsToRemove.addAll(it) }

            // delete header param from the right table
            collectHeaderParams(cloneRightHeaderLine) {
                it < columnNumber && !uniqueColumns.contains(it)
            }.also { elementsToRemove.addAll(it) }

            withContext(Dispatchers.EDT) {
                PostprocessReformattingAspect.getInstance(project).disablePostprocessFormattingInside {
                    runWithModalProgressBlocking(project, "Splitting table by '${headerParameter.text}' column") {
                        elementsToRemove.forEachWithProgress {
                            WriteCommandAction.runWriteCommandAction(
                                project, commandName, groupID,
                                { it.delete() },
                                psiFile
                            )
                        }
                    }
                }
            }

            // perform actual modification of the document, also inject a few new lines for the right cloned table
            val cloneLeftTableText = readAction { cloneTableLeft.text }
            val cloneRightTableText = readAction { "\n" + cloneTableRight.text }

            withContext(Dispatchers.EDT) {
                PostprocessReformattingAspect.getInstance(project).disablePostprocessFormattingInside {
                    runWithModalProgressBlocking(project, "Splitting table by '${headerParameter.text}' column") {
                        WriteCommandAction.runWriteCommandAction(
                            project, commandName, groupID,
                            {
                                editor.document.replaceString(tableRange.startOffset, tableRange.endOffset, cloneLeftTableText)
                                editor.document.insertString(tableRange.startOffset + cloneLeftTableText.length, cloneRightTableText)
                            },
                            psiFile
                        )
                    }
                }

                val cloneStartRightTable = tableRange.startOffset + cloneLeftTableText.length + 1

                editor.caretModel.moveToOffset(cloneStartRightTable)
                editor.selectionModel.setSelection(cloneStartRightTable, cloneStartRightTable + cloneRightTableText.length - 2)
                editor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE)
            }
        }
    }