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)
}
}
}