Better caret position after Insert curly braces around variable (KT-28739)

Introduce helper class and move caret to it's original position.

 #KT-28739 Fixed
This commit is contained in:
Nikolay Krasko
2018-12-10 18:15:25 +03:00
parent 44a36e70ec
commit 5fb90a8a81
11 changed files with 97 additions and 7 deletions
@@ -44,6 +44,66 @@ fun moveCaretIntoGeneratedElement(editor: Editor, element: PsiElement) {
pointer.element?.let { moveCaretIntoGeneratedElementDocumentUnblocked(editor, it) }
}
class RestoreCaret<T: PsiElement>(beforeElement: T, val editor: Editor?) {
private val relativeOffset: Int
private val beforeElementTextLength: Int = beforeElement.textLength
init {
relativeOffset = findRelativeOffset(beforeElement, editor)
}
fun restoreCaret(afterElement: T, defaultOffset: ((element: T) -> Int)? = null) {
if (editor == null) return
val project = editor.project ?: return
val pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(afterElement)
val document = editor.document
PsiDocumentManager.getInstance(project).commitDocument(document)
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document)
val afterElementChanged = pointer.element ?: return
val offset = if (relativeOffset != -1 && afterElementChanged.textLength == beforeElementTextLength) {
afterElementChanged.startOffset + relativeOffset
} else {
if (defaultOffset != null) {
defaultOffset(afterElementChanged)
} else {
-1
}
}
if (offset == -1) {
return
}
if (document.textLength > offset) {
editor.caretModel.moveToOffset(offset)
}
}
companion object {
fun findRelativeOffset(element: PsiElement, editor: Editor?): Int {
if (editor != null) {
val singleCaret = editor.caretModel.allCarets.singleOrNull()
if (singleCaret != null) {
val caretOffset = singleCaret.offset
val textRange = element.textRange
if (textRange.startOffset <= caretOffset && caretOffset <= textRange.endOffset) {
val relative = caretOffset - element.startOffset
if (relative >= 0) {
return relative
}
}
}
}
return -1
}
}
}
private fun moveCaretIntoGeneratedElementDocumentUnblocked(editor: Editor, element: PsiElement): Boolean {
// Inspired by GenerateMembersUtils.positionCaret()