[formatter] fix performance issue

^KT-41314 Fixed
This commit is contained in:
Dmitry Gridin
2020-08-27 16:31:37 +07:00
parent 9818321b46
commit 0c0b394cc2
3 changed files with 21 additions and 21 deletions
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
import org.jetbrains.kotlin.idea.formatter.NodeIndentStrategy.Companion.strategy import org.jetbrains.kotlin.idea.formatter.NodeIndentStrategy.Companion.strategy
import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaHelper.trailingCommaExistsOrCanExist import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaHelper.trailingCommaExistsOrCanExist
import org.jetbrains.kotlin.idea.formatter.trailingComma.addTrailingCommaIsAllowedFor import org.jetbrains.kotlin.idea.formatter.trailingComma.addTrailingCommaIsAllowedFor
import org.jetbrains.kotlin.idea.util.containsLineBreakInThis import org.jetbrains.kotlin.idea.util.containsLineBreakInChild
import org.jetbrains.kotlin.idea.util.isMultiline import org.jetbrains.kotlin.idea.util.isMultiline
import org.jetbrains.kotlin.idea.util.requireNode import org.jetbrains.kotlin.idea.util.requireNode
import org.jetbrains.kotlin.kdoc.lexer.KDocTokens import org.jetbrains.kotlin.kdoc.lexer.KDocTokens
@@ -757,7 +757,7 @@ abstract class KotlinCommonBlock(
?: psi.startOffset ?: psi.startOffset
val endOffset = childElement.notDelimiterSiblingNodeInSequence(true, delimiterType, typeOfLastElement)?.psi?.endOffset val endOffset = childElement.notDelimiterSiblingNodeInSequence(true, delimiterType, typeOfLastElement)?.psi?.endOffset
?: psi.endOffset ?: psi.endOffset
return psi.parent.containsLineBreakInThis(startOffset, endOffset) return psi.parent.containsLineBreakInChild(startOffset, endOffset)
} }
private fun trailingCommaWrappingStrategyWithMultiLineCheck( private fun trailingCommaWrappingStrategyWithMultiLineCheck(
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.idea.formatter.trailingComma package org.jetbrains.kotlin.idea.formatter.trailingComma
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.util.containsLineBreakInThis import org.jetbrains.kotlin.idea.util.containsLineBreakInChild
import org.jetbrains.kotlin.idea.util.isMultiline import org.jetbrains.kotlin.idea.util.isMultiline
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
@@ -86,5 +86,5 @@ private fun <T : PsiElement> T.isMultiline(
): Boolean { ): Boolean {
val startOffset = startOffsetGetter() ?: startOffset val startOffset = startOffsetGetter() ?: startOffset
val endOffset = endOffsetGetter() ?: endOffset val endOffset = endOffsetGetter() ?: endOffset
return containsLineBreakInThis(startOffset, endOffset) return containsLineBreakInChild(startOffset, endOffset)
} }
@@ -15,9 +15,7 @@ import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.util.PsiUtil import com.intellij.psi.util.PsiUtil
import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.psiUtil.nextLeaf import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
import org.jetbrains.kotlin.psi.psiUtil.startOffset
/* /*
* ASTBlock.node is nullable, this extension was introduced to minimize changes * ASTBlock.node is nullable, this extension was introduced to minimize changes
@@ -31,19 +29,19 @@ val isDefaultOfficialCodeStyle by lazy { !KotlinCodeStyleSettings.defaultSetting
// Copied from idea-core // Copied from idea-core
fun PsiElement.getLineCount(): Int { fun PsiElement.getLineCount(): Int {
val doc = containingFile?.let { PsiDocumentManager.getInstance(project).getDocument(it) } val spaceRange = textRange ?: TextRange.EMPTY_RANGE
if (doc != null) { return getLineCountByDocument(spaceRange.startOffset, spaceRange.endOffset)
val spaceRange = textRange ?: TextRange.EMPTY_RANGE ?: StringUtil.getLineBreakCount(text ?: error("Cannot count number of lines")) + 1
}
if (spaceRange.endOffset <= doc.textLength && spaceRange.startOffset < spaceRange.endOffset) { fun PsiElement.getLineCountByDocument(startOffset: Int, endOffset: Int): Int? {
val startLine = doc.getLineNumber(spaceRange.startOffset) val doc = containingFile?.let { PsiDocumentManager.getInstance(project).getDocument(it) } ?: return null
val endLine = doc.getLineNumber(spaceRange.endOffset) if (endOffset > doc.textLength || startOffset >= endOffset) return null
return endLine - startLine + 1 val startLine = doc.getLineNumber(startOffset)
} val endLine = doc.getLineNumber(endOffset)
}
return StringUtil.getLineBreakCount(text ?: error("Cannot count number of lines")) + 1 return endLine - startLine + 1
} }
fun PsiElement.isMultiline() = getLineCount() > 1 fun PsiElement.isMultiline() = getLineCount() > 1
@@ -62,7 +60,9 @@ fun PsiElement.leaf(forward: Boolean = true, filter: (PsiElement) -> Boolean): P
val PsiElement.isComma: Boolean get() = PsiUtil.getElementType(this) == KtTokens.COMMA val PsiElement.isComma: Boolean get() = PsiUtil.getElementType(this) == KtTokens.COMMA
fun PsiElement.containsLineBreakInThis(globalStartOffset: Int, globalEndOffset: Int): Boolean { fun PsiElement.containsLineBreakInChild(globalStartOffset: Int, globalEndOffset: Int): Boolean =
val textRange = TextRange.create(globalStartOffset, globalEndOffset).shiftLeft(startOffset) getLineCountByDocument(globalStartOffset, globalEndOffset)?.let { it > 1 }
return StringUtil.containsLineBreak(textRange.subSequence(text)) ?: firstChild.siblings(forward = true, withItself = true)
} .dropWhile { it.startOffset < globalStartOffset }
.takeWhile { it.endOffset <= globalEndOffset }
.any { it.textContains('\n') || it.textContains('\r') }