mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[remDev] [kotlin] enable joinLines on frontend
- JoinInitializerAndIfToElvisHandler requires resolve - JoinBlockIntoSingleStatementHandler requires CommentSaver, let's postpone ^KTIJ-35294 fixed GitOrigin-RevId: 1c518197f7b9ef537f2a76d718aba2748c200bd7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
313dbb2033
commit
3d1cc196a5
@@ -22,5 +22,12 @@
|
||||
<lang.foldingBuilder
|
||||
language="kotlin"
|
||||
implementationClass="org.jetbrains.kotlin.idea.KotlinFoldingBuilder"/>
|
||||
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinDeclarationAndAssignmentHandler"/>
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinStatementsAddSemicolonHandler"/>
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinWhenEntryHandler"/>
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinWithTrailingCommaHandler"/>
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinToStringTemplateHandler"/>
|
||||
|
||||
</extensions>
|
||||
</idea-plugin>
|
||||
+8
-9
@@ -1,8 +1,7 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.joinLines
|
||||
|
||||
import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate
|
||||
import com.intellij.codeInsight.editorActions.JoinRawLinesHandlerDelegate
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
@@ -10,9 +9,9 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.util.elementType
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
@@ -22,18 +21,18 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
|
||||
class JoinDeclarationAndAssignmentHandler : JoinRawLinesHandlerDelegate {
|
||||
override fun tryJoinRawLines(document: Document, file: PsiFile, start: Int, end: Int): Int {
|
||||
if (file !is KtFile) return CANNOT_JOIN
|
||||
if (file.fileType !is KotlinFileType) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
val element = file.findElementAt(start)
|
||||
?.siblings(forward = false, withItself = false)
|
||||
?.firstOrNull { !isToSkip(it) } ?: return CANNOT_JOIN
|
||||
?.firstOrNull { !isToSkip(it) } ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
val (property, assignment) = element.parentsWithSelf.mapNotNull { getPropertyAndAssignment(it) }.firstOrNull() ?: return CANNOT_JOIN
|
||||
val (property, assignment) = element.parentsWithSelf.mapNotNull { getPropertyAndAssignment(it) }.firstOrNull() ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
document.replaceString(property.endOffset, assignment.operationReference.startOffset, " ")
|
||||
return property.startOffset
|
||||
}
|
||||
|
||||
override fun tryJoinLines(document: Document, file: PsiFile, start: Int, end: Int) = CANNOT_JOIN
|
||||
override fun tryJoinLines(document: Document, file: PsiFile, start: Int, end: Int) = JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
private fun getPropertyAndAssignment(element: PsiElement): Pair<KtProperty, KtBinaryExpression>? {
|
||||
val property = element as? KtProperty ?: return null
|
||||
@@ -55,4 +54,4 @@ class JoinDeclarationAndAssignmentHandler : JoinRawLinesHandlerDelegate {
|
||||
is PsiWhiteSpace -> StringUtil.getLineBreakCount(element.text) <= 1 // do not skip blank line
|
||||
else -> element.elementType == KtTokens.SEMICOLON
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-23
@@ -1,17 +1,15 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.joinLines
|
||||
|
||||
import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate
|
||||
import com.intellij.codeInsight.editorActions.JoinRawLinesHandlerDelegate
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.KtNodeTypes.BLOCK
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.LBRACE
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.parsing.KotlinExpressionParsing
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtPropertyAccessor
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
@@ -19,34 +17,34 @@ import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
class JoinStatementsAddSemicolonHandler : JoinRawLinesHandlerDelegate {
|
||||
|
||||
override fun tryJoinRawLines(document: Document, file: PsiFile, start: Int, end: Int): Int {
|
||||
if (file !is KtFile) return CANNOT_JOIN
|
||||
if (file.fileType !is KotlinFileType) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
val linebreak = file.findElementAt(start)
|
||||
?.siblings(forward = true, withItself = true)
|
||||
?.firstOrNull { it.textContains('\n') }
|
||||
?: return CANNOT_JOIN
|
||||
?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
val parent = linebreak.parent ?: return CANNOT_JOIN
|
||||
val element1 = linebreak.firstMaterialSiblingSameLine { prevSibling } ?: return CANNOT_JOIN
|
||||
val element2 = linebreak.firstMaterialSiblingSameLine { nextSibling } ?: return CANNOT_JOIN
|
||||
val parent = linebreak.parent ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
val element1 = linebreak.firstMaterialSiblingSameLine { prevSibling } ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
val element2 = linebreak.firstMaterialSiblingSameLine { nextSibling } ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
if (linebreak.text.count { it == '\n' } > 1) return CANNOT_JOIN
|
||||
if (linebreak.text.count { it == '\n' } > 1) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
if (element1 !is KtPropertyAccessor) {
|
||||
val parentOfElement1 = element1.parent
|
||||
if (parentOfElement1 is KtProperty && parentOfElement1.initializer == null && element2 is KtPropertyAccessor) {
|
||||
return CANNOT_JOIN
|
||||
return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(element1 !is KtPropertyAccessor && element2 !is KtPropertyAccessor) &&
|
||||
// `val x=1 fun f(){}` is error; while `fun f(){} val x=1` is OK
|
||||
(element1 !is KtProperty)
|
||||
(element1 !is KtPropertyAccessor && element2 !is KtPropertyAccessor) &&
|
||||
// `val x=1 fun f(){}` is error; while `fun f(){} val x=1` is OK
|
||||
(element1 !is KtProperty)
|
||||
) {
|
||||
if (parent.node.elementType != BLOCK) return CANNOT_JOIN
|
||||
if (!element1.isStatement()) return CANNOT_JOIN
|
||||
if (!element2.isStatement()) return CANNOT_JOIN
|
||||
if (parent.node.elementType != KtNodeTypes.BLOCK) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
if (!element1.isStatement()) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
if (!element2.isStatement()) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
}
|
||||
|
||||
document.replaceString(linebreak.textRange.startOffset, linebreak.textRange.endOffset, " ")
|
||||
@@ -55,13 +53,13 @@ class JoinStatementsAddSemicolonHandler : JoinRawLinesHandlerDelegate {
|
||||
return linebreak.textRange.startOffset + 1
|
||||
}
|
||||
|
||||
override fun tryJoinLines(document: Document, file: PsiFile, start: Int, end: Int): Int = CANNOT_JOIN
|
||||
override fun tryJoinLines(document: Document, file: PsiFile, start: Int, end: Int): Int = JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
private fun PsiElement.firstMaterialSiblingSameLine(getNext: PsiElement.() -> PsiElement?): PsiElement? {
|
||||
var element = this
|
||||
do {
|
||||
element = element.getNext() ?: return null
|
||||
if (element.node.elementType !in WHITE_SPACE_OR_COMMENT_BIT_SET)
|
||||
if (element.node.elementType !in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET)
|
||||
return element
|
||||
} while (!element.textContains('\n'))
|
||||
|
||||
@@ -69,7 +67,7 @@ class JoinStatementsAddSemicolonHandler : JoinRawLinesHandlerDelegate {
|
||||
}
|
||||
|
||||
private fun PsiElement.isStatement(): Boolean {
|
||||
if (this.node.elementType == LBRACE) return false
|
||||
if (this.node.elementType == KtTokens.LBRACE) return false
|
||||
|
||||
var firstSubElement: PsiElement = this
|
||||
while (true) firstSubElement = firstSubElement.firstChild ?: break
|
||||
+18
-16
@@ -1,30 +1,32 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.joinLines
|
||||
|
||||
import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate
|
||||
import com.intellij.codeInsight.editorActions.JoinRawLinesHandlerDelegate
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.idea.base.psi.getLineCount
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.util.getLineCount
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtOperationReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.KtStringTemplateExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.util.match
|
||||
|
||||
class JoinToStringTemplateHandler : JoinRawLinesHandlerDelegate {
|
||||
override fun tryJoinRawLines(document: Document, file: PsiFile, start: Int, end: Int): Int {
|
||||
if (file !is KtFile) return -1
|
||||
if (file.fileType !is KotlinFileType) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
if (start == 0) return -1
|
||||
if (start == 0) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
val c = document.charsSequence[start]
|
||||
val index = if (c == '\n') start - 1 else start
|
||||
|
||||
val plus = file.findElementAt(index)?.takeIf { it.node?.elementType == KtTokens.PLUS } ?: return -1
|
||||
var binaryExpr = plus.parents.match(KtOperationReferenceExpression::class, last = KtBinaryExpression::class)
|
||||
val plus = file.findElementAt(index)?.takeIf { it.node?.elementType == KtTokens.PLUS } ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
var binaryExpr = ((plus.parent as? KtOperationReferenceExpression)?.parent as? KtBinaryExpression)
|
||||
?.takeIf(KtBinaryExpression::joinable)
|
||||
?: return -1
|
||||
?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
val lineCount = binaryExpr.getLineCount()
|
||||
|
||||
@@ -37,7 +39,7 @@ class JoinToStringTemplateHandler : JoinRawLinesHandlerDelegate {
|
||||
var rightText = unescape(binaryExpr.right as KtStringTemplateExpression)
|
||||
var left = binaryExpr.left
|
||||
while (left is KtBinaryExpression && left.joinable()) {
|
||||
val leftLeft = (left as? KtBinaryExpression)?.left ?: break
|
||||
val leftLeft = left.left ?: break
|
||||
if (leftLeft.getLineCount() < lineCount - 1) break
|
||||
rightText = unescape(left.right as KtStringTemplateExpression) + rightText
|
||||
left = left.left
|
||||
@@ -57,10 +59,10 @@ class JoinToStringTemplateHandler : JoinRawLinesHandlerDelegate {
|
||||
binaryExpr.replace(left)
|
||||
offset
|
||||
} else {
|
||||
-1
|
||||
JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
}
|
||||
}
|
||||
else -> -1
|
||||
else -> JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +81,7 @@ class JoinToStringTemplateHandler : JoinRawLinesHandlerDelegate {
|
||||
return KtPsiFactory(left.project).createExpression("\"$leftText$rightText\"") as KtStringTemplateExpression
|
||||
}
|
||||
|
||||
override fun tryJoinLines(document: Document, file: PsiFile, start: Int, end: Int): Int = -1
|
||||
override fun tryJoinLines(document: Document, file: PsiFile, start: Int, end: Int): Int = JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
}
|
||||
|
||||
private fun KtBinaryExpression.joinable(): Boolean {
|
||||
@@ -90,4 +92,4 @@ private fun KtBinaryExpression.joinable(): Boolean {
|
||||
is KtBinaryExpression -> left.right is KtStringTemplateExpression
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
-20
@@ -1,39 +1,46 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.joinLines
|
||||
|
||||
import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate
|
||||
import com.intellij.codeInsight.editorActions.JoinRawLinesHandlerDelegate
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.psi.KtWhenEntry
|
||||
import org.jetbrains.kotlin.psi.KtWhenExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.allChildren
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespace
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespace
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments
|
||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
|
||||
class JoinWhenEntryHandler : JoinRawLinesHandlerDelegate {
|
||||
override fun tryJoinRawLines(document: Document, file: PsiFile, start: Int, end: Int): Int {
|
||||
if (file !is KtFile) return CANNOT_JOIN
|
||||
val element = file.findElementAt(start) ?: return CANNOT_JOIN
|
||||
if (file.fileType !is KotlinFileType) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
val element = file.findElementAt(start) ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
val entry = element.getPrevSiblingIgnoringWhitespaceAndComments() as? KtWhenEntry ?: return CANNOT_JOIN
|
||||
val entryLastCondition = entry.conditions.lastOrNull() ?: return CANNOT_JOIN
|
||||
val whenExpression = entry.parent as? KtWhenExpression ?: return CANNOT_JOIN
|
||||
val entry = element.getPrevSiblingIgnoringWhitespaceAndComments() as? KtWhenEntry ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
val entryLastCondition = entry.conditions.lastOrNull() ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
val whenExpression = entry.parent as? KtWhenExpression ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
val prevSiblingIgnoringWhitespace = element.getPrevSiblingIgnoringWhitespace()
|
||||
val nextSiblingIgnoringWhitespace = element.getNextSiblingIgnoringWhitespace()
|
||||
|
||||
if (nextSiblingIgnoringWhitespace is PsiComment && nextSiblingIgnoringWhitespace.noKtWhenEntryTillNewLine())
|
||||
return CANNOT_JOIN
|
||||
return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
val nextEntry = entry.getNextSiblingIgnoringWhitespaceAndComments() as? KtWhenEntry ?: return CANNOT_JOIN
|
||||
val nextEntry = entry.getNextSiblingIgnoringWhitespaceAndComments() as? KtWhenEntry ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
if (nextEntry.isElse) return CANNOT_JOIN
|
||||
if (nextEntry.isElse) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
if (element is PsiWhiteSpace && element.text.contains('\n') && element.noKtWhenEntryTillNewLine(false))
|
||||
return CANNOT_JOIN
|
||||
return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
if (entry.hasComments() || nextEntry.hasComments() || !nextEntry.hasSameExpression(entry)) {
|
||||
return joinWithSemicolon(document,
|
||||
@@ -41,28 +48,28 @@ class JoinWhenEntryHandler : JoinRawLinesHandlerDelegate {
|
||||
nextSiblingIgnoringWhitespace ?: nextEntry)
|
||||
}
|
||||
|
||||
val nextEntryFirstCondition = nextEntry.conditions.firstOrNull() ?: return CANNOT_JOIN
|
||||
val nextEntryFirstCondition = nextEntry.conditions.firstOrNull() ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
val separator = if (whenExpression.subjectExpression != null) ", " else " || "
|
||||
document.replaceString(entryLastCondition.endOffset, nextEntryFirstCondition.startOffset, separator)
|
||||
return entry.startOffset
|
||||
}
|
||||
|
||||
private fun joinWithSemicolon(
|
||||
document: Document,
|
||||
entry: PsiElement,
|
||||
nextEntry: PsiElement
|
||||
document: Document,
|
||||
entry: PsiElement,
|
||||
nextEntry: PsiElement
|
||||
): Int {
|
||||
document.replaceString(entry.textRange.endOffset, nextEntry.textRange.startOffset, "; ")
|
||||
return entry.textRange.endOffset + 1
|
||||
}
|
||||
|
||||
override fun tryJoinLines(document: Document, file: PsiFile, start: Int, end: Int): Int = CANNOT_JOIN
|
||||
override fun tryJoinLines(document: Document, file: PsiFile, start: Int, end: Int): Int = JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
private fun KtWhenEntry.hasComments(): Boolean =
|
||||
allChildren.any { it is PsiComment } || siblings(withItself = false).takeWhile { !it.textContains('\n') }.any { it is PsiComment }
|
||||
allChildren.any { it is PsiComment } || siblings(withItself = false).takeWhile { !it.textContains('\n') }.any { it is PsiComment }
|
||||
|
||||
private fun KtWhenEntry.hasSameExpression(other: KtWhenEntry) = expression?.text == other.expression?.text
|
||||
|
||||
private fun PsiElement.noKtWhenEntryTillNewLine(forward: Boolean = true) =
|
||||
siblings(forward = forward, withItself = false).takeWhile { !it.textContains('\n') }.none { it is KtWhenEntry }
|
||||
}
|
||||
}
|
||||
+14
-13
@@ -1,10 +1,9 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.kotlin.idea.joinLines
|
||||
|
||||
import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate
|
||||
import com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
@@ -12,29 +11,29 @@ import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import com.intellij.psi.util.elementType
|
||||
import com.intellij.psi.util.nextLeaf
|
||||
import org.jetbrains.kotlin.idea.base.psi.containsLineBreakInRange
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaHelper
|
||||
import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaState
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import kotlin.math.abs
|
||||
|
||||
class JoinWithTrailingCommaHandler : JoinLinesHandlerDelegate {
|
||||
override fun tryJoinLines(document: Document, file: PsiFile, start: Int, end: Int): Int {
|
||||
if (file !is KtFile) return CANNOT_JOIN
|
||||
if (file.fileType !is KotlinFileType) return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
val startElement = file.findElementAt(start)
|
||||
val commaOwner = startElement
|
||||
?.parentsWithSelf
|
||||
?.filter { !document.containsLineBreakInRange(it.textRange) }
|
||||
?.filter { !(document.getLineCountInRange(it.textRange) != 0) }
|
||||
?.find { TrailingCommaState.stateForElement(it) == TrailingCommaState.REDUNDANT } as? KtElement
|
||||
?: return CANNOT_JOIN
|
||||
?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
val comma = TrailingCommaHelper.trailingCommaOrLastElement(commaOwner)?.takeIf {
|
||||
it.elementType == KtTokens.COMMA
|
||||
} ?: return CANNOT_JOIN
|
||||
} ?: return JoinLinesHandlerDelegate.CANNOT_JOIN
|
||||
|
||||
comma.nextWhiteSpaceOrNull()?.delete()
|
||||
deleteOrReplaceWithWhiteSpace(comma, comma.nextLeaf()?.elementType)
|
||||
@@ -45,10 +44,10 @@ class JoinWithTrailingCommaHandler : JoinLinesHandlerDelegate {
|
||||
}
|
||||
|
||||
private val TOKENS_WITH_SPACES = TokenSet.create(
|
||||
KtTokens.ARROW,
|
||||
KtTokens.RBRACE,
|
||||
KtTokens.LBRACE,
|
||||
KtTokens.COMMA,
|
||||
KtTokens.ARROW,
|
||||
KtTokens.RBRACE,
|
||||
KtTokens.LBRACE,
|
||||
KtTokens.COMMA,
|
||||
)
|
||||
|
||||
private fun deleteOrReplaceWithWhiteSpace(element: PsiElement, type: IElementType?) {
|
||||
@@ -60,3 +59,5 @@ private fun deleteOrReplaceWithWhiteSpace(element: PsiElement, type: IElementTyp
|
||||
}
|
||||
|
||||
private fun PsiElement.nextWhiteSpaceOrNull(): PsiElement? = nextLeaf().takeIf { it is PsiWhiteSpace }
|
||||
|
||||
fun Document.getLineCountInRange(textRange: TextRange): Int = abs(getLineNumber(textRange.startOffset) - getLineNumber(textRange.endOffset))
|
||||
@@ -8,6 +8,7 @@ import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.DocumentUtil
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import kotlin.math.abs
|
||||
@@ -74,4 +75,7 @@ fun PsiElement.isOneLiner() = getLineCount() == 1
|
||||
|
||||
fun Document.getLineCountInRange(textRange: TextRange): Int = abs(getLineNumber(textRange.startOffset) - getLineNumber(textRange.endOffset))
|
||||
|
||||
@Deprecated("Please use DocumentUtil.getLineCountInRange() instead", ReplaceWith("getLineCountInRange(textRange) != 0"))
|
||||
@Suppress("unused", "DeprecatedCallableAddReplaceWith")
|
||||
@ApiStatus.ScheduledForRemoval
|
||||
fun Document.containsLineBreakInRange(textRange: TextRange): Boolean = getLineCountInRange(textRange) != 0
|
||||
|
||||
@@ -368,13 +368,8 @@
|
||||
|
||||
<editorSmartKeysConfigurable instance="org.jetbrains.kotlin.idea.editor.KotlinEditorOptionsConfigurable"/>
|
||||
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinDeclarationAndAssignmentHandler"/>
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinInitializerAndIfToElvisHandler"/>
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinBlockIntoSingleStatementHandler"/>
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinStatementsAddSemicolonHandler"/>
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinToStringTemplateHandler"/>
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinWithTrailingCommaHandler"/>
|
||||
<joinLinesHandler implementation="org.jetbrains.kotlin.idea.joinLines.JoinWhenEntryHandler"/>
|
||||
|
||||
<quoteHandler fileType="Kotlin" className="org.jetbrains.kotlin.idea.editor.KotlinQuoteHandler"/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user