diff --git a/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt b/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt index 83fb6daa87d..557d4ddade0 100644 --- a/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt +++ b/idea/formatter/src/org/jetbrains/kotlin/idea/util/FormatterUtil.kt @@ -29,6 +29,7 @@ fun ASTBlock.requireNode() = node ?: error("ASTBlock.getNode() returned null") */ val isDefaultOfficialCodeStyle by lazy { !KotlinCodeStyleSettings.defaultSettings().CONTINUATION_INDENT_FOR_CHAINED_CALLS } +// Copied from idea-core fun PsiElement.getLineCount(): Int { val doc = containingFile?.let { PsiDocumentManager.getInstance(project).getDocument(it) } if (doc != null) { @@ -36,13 +37,13 @@ fun PsiElement.getLineCount(): Int { if (spaceRange.endOffset <= doc.textLength && spaceRange.startOffset < spaceRange.endOffset) { val startLine = doc.getLineNumber(spaceRange.startOffset) - val endLine = doc.getLineNumber(spaceRange.endOffset - 1) + val endLine = doc.getLineNumber(spaceRange.endOffset) return endLine - startLine + 1 } } - return StringUtil.getLineBreakCount(text ?: "") + 1 + return StringUtil.getLineBreakCount(text ?: error("Cannot count number of lines")) + 1 } fun PsiElement.isMultiline() = getLineCount() > 1 diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/PsiLinesUtils.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/PsiLinesUtils.kt index 93dee301d46..2b36ae8c95f 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/PsiLinesUtils.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/util/PsiLinesUtils.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.core.util import com.intellij.openapi.editor.Document import com.intellij.openapi.util.TextRange +import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.* import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.psi.psiUtil.endOffset @@ -42,23 +43,26 @@ fun PsiElement.getLineNumber(start: Boolean = true): Int { return document?.getLineNumber(if (start) this.startOffset else this.endOffset) ?: 0 } +// Copied to formatter fun PsiElement.getLineCount(): Int { val doc = containingFile?.let { file -> PsiDocumentManager.getInstance(project).getDocument(file) } if (doc != null) { val spaceRange = textRange ?: TextRange.EMPTY_RANGE - if (spaceRange.endOffset <= doc.textLength) { + if (spaceRange.endOffset <= doc.textLength && spaceRange.startOffset < spaceRange.endOffset) { val startLine = doc.getLineNumber(spaceRange.startOffset) val endLine = doc.getLineNumber(spaceRange.endOffset) - return endLine - startLine + return endLine - startLine + 1 } } - return (text ?: "").count { it == '\n' } + 1 + return StringUtil.getLineBreakCount(text ?: error("Cannot count number of lines")) + 1 } -fun PsiElement.isMultiLine(): Boolean = getLineCount() > 1 +fun PsiElement.isMultiLine() = getLineCount() > 1 + +fun PsiElement.isOneLiner() = getLineCount() == 1 fun Document.getLineCountInRange(textRange: TextRange): Int = abs(getLineNumber(textRange.startOffset) - getLineNumber(textRange.endOffset)) diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractBreakpointApplicabilityTest.kt b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractBreakpointApplicabilityTest.kt index 62e1c42ab5a..cac59fb6d92 100644 --- a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractBreakpointApplicabilityTest.kt +++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractBreakpointApplicabilityTest.kt @@ -35,7 +35,7 @@ abstract class AbstractBreakpointApplicabilityTest : KotlinLightCodeInsightFixtu private fun checkBreakpoints(file: KtFile, checker: BreakpointChecker): String { val lineCount = file.getLineCount() - return (0..lineCount).joinToString("\n") { line -> checkLine(file, line, checker) } + return (0 until lineCount).joinToString("\n") { line -> checkLine(file, line, checker) } } private fun checkLine(file: KtFile, line: Int, checker: BreakpointChecker): String { diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInsight/upDownMover/KotlinExpressionMover.kt b/idea/src/org/jetbrains/kotlin/idea/codeInsight/upDownMover/KotlinExpressionMover.kt index 35370ffa94e..5e8129c8ab9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInsight/upDownMover/KotlinExpressionMover.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInsight/upDownMover/KotlinExpressionMover.kt @@ -10,6 +10,7 @@ import com.intellij.codeInsight.editorActions.moveUpDown.StatementUpDownMover import com.intellij.openapi.editor.Editor import com.intellij.psi.* import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.idea.core.util.getLineCount import org.jetbrains.kotlin.idea.core.util.isMultiLine import org.jetbrains.kotlin.idea.formatter.trailingComma.TrailingCommaHelper import org.jetbrains.kotlin.idea.util.isComma @@ -552,7 +553,7 @@ class KotlinExpressionMover : AbstractKotlinUpDownMover() { } if (whiteSpaceTestSubject is PsiWhiteSpace) { - if (whiteSpaceTestSubject.isMultiLine()) { + if (whiteSpaceTestSubject.getLineCount() >= 3) { val nearLine = if (down) sourceRange.endLine else sourceRange.startLine - 1 info.toMove = sourceRange info.toMove2 = LineRange(nearLine, nearLine + 1) diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/CascadeIfInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/CascadeIfInspection.kt index bcbf9f6664c..26f02cb6bf2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/CascadeIfInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/CascadeIfInspection.kt @@ -10,9 +10,9 @@ import com.intellij.codeInspection.LocalInspectionToolSession import com.intellij.codeInspection.ProblemHighlightType import com.intellij.codeInspection.ProblemsHolder import org.jetbrains.kotlin.idea.KotlinBundle +import org.jetbrains.kotlin.idea.core.util.isOneLiner import org.jetbrains.kotlin.idea.intentions.branchedTransformations.intentions.IfToWhenIntention import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isElseIf -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isOneLiner import org.jetbrains.kotlin.idea.intentions.branches import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/LiftReturnOrAssignmentInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/LiftReturnOrAssignmentInspection.kt index 0458ad8472a..851da34c0b1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/LiftReturnOrAssignmentInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/LiftReturnOrAssignmentInspection.kt @@ -23,9 +23,9 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.core.util.getLineCount import org.jetbrains.kotlin.idea.intentions.branchedTransformations.BranchedFoldingUtils import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isElseIf -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.lineCount import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.startOffset @@ -115,7 +115,7 @@ class LiftReturnOrAssignmentInspection @JvmOverloads constructor(private val ski keyword: PsiElement, skipLongExpressions: Boolean ): List? { - if (skipLongExpressions && expression.lineCount() > LINES_LIMIT) return null + if (skipLongExpressions && expression.getLineCount() > LINES_LIMIT) return null if (expression.isElseIf()) return null val foldableReturns = BranchedFoldingUtils.getFoldableReturns(expression) diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/MoveVariableDeclarationIntoWhenInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/MoveVariableDeclarationIntoWhenInspection.kt index a309811b610..d41bfd2d260 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/MoveVariableDeclarationIntoWhenInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/MoveVariableDeclarationIntoWhenInspection.kt @@ -17,7 +17,7 @@ import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.SmartPsiElementPointer import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.idea.core.moveCaret -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isOneLiner +import org.jetbrains.kotlin.idea.core.util.isOneLiner import org.jetbrains.kotlin.idea.intentions.loopToCallChain.countUsages import org.jetbrains.kotlin.idea.intentions.loopToCallChain.previousStatement import org.jetbrains.kotlin.lexer.KtTokens diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLetInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLetInspection.kt index a75bfd23557..ae5c139cdd4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLetInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantLetInspection.kt @@ -14,8 +14,9 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.idea.KotlinBundle import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.core.replaced +import org.jetbrains.kotlin.idea.core.util.getLineCount +import org.jetbrains.kotlin.idea.core.util.isMultiLine import org.jetbrains.kotlin.idea.intentions.* -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.lineCount import org.jetbrains.kotlin.idea.util.textRangeIn import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* @@ -249,7 +250,7 @@ private fun KtFunctionLiteral.valueParameterReferences(callExpression: KtCallExp private fun isSingleLine(element: KtCallExpression): Boolean { val qualifiedExpression = element.getQualifiedExpressionForSelector() ?: return true var receiver = qualifiedExpression.receiverExpression - if (receiver.lineCount() > 1) return false + if (receiver.isMultiLine()) return false var count = 1 while (true) { if (count > 2) return false diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/UseExpressionBodyInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/UseExpressionBodyInspection.kt index b71b8f559d5..e651f97d0a5 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/UseExpressionBodyInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/UseExpressionBodyInspection.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.core.canOmitDeclaredType import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.core.setType -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isOneLiner +import org.jetbrains.kotlin.idea.core.util.isOneLiner import org.jetbrains.kotlin.idea.intentions.hasResultingIfWithoutElse import org.jetbrains.kotlin.idea.intentions.resultingWhens import org.jetbrains.kotlin.idea.util.CommentSaver diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt index bed2ad93e1d..5024d359223 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/branchedTransformations/IfThenUtils.kt @@ -361,13 +361,4 @@ private fun KtExpression.insertSafeCalls(factory: KtPsiFactory): KtExpression { return replaced } -// Returns -1 if cannot obtain a document -internal fun KtExpression.lineCount(): Int { - val file = containingFile?.virtualFile ?: return -1 - val document = FileDocumentManager.getInstance().getDocument(file) ?: return -1 - return document.getLineNumber(textRange.endOffset) - document.getLineNumber(textRange.startOffset) + 1 -} - -internal fun KtExpression.isOneLiner(): Boolean = lineCount() == 1 - internal fun KtExpression.isElseIf() = parent.node.elementType == KtNodeTypes.ELSE diff --git a/idea/src/org/jetbrains/kotlin/idea/joinLines/JoinToStringTemplateHandler.kt b/idea/src/org/jetbrains/kotlin/idea/joinLines/JoinToStringTemplateHandler.kt index f31484594cf..8f17aa17e73 100644 --- a/idea/src/org/jetbrains/kotlin/idea/joinLines/JoinToStringTemplateHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/joinLines/JoinToStringTemplateHandler.kt @@ -21,12 +21,8 @@ import com.intellij.openapi.editor.Document import com.intellij.psi.PsiFile import org.jetbrains.kotlin.idea.core.util.getLineCount import org.jetbrains.kotlin.idea.intentions.ConvertToStringTemplateIntention -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.lineCount import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtPsiFactory -import org.jetbrains.kotlin.psi.KtStringTemplateExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset class JoinToStringTemplateHandler : JoinRawLinesHandlerDelegate { @@ -42,10 +38,9 @@ class JoinToStringTemplateHandler : JoinRawLinesHandlerDelegate { if (!binaryExpr.joinable()) return -1 val lineCount = binaryExpr.getLineCount() - val nextLineCount = lineCount + 1 var parent = binaryExpr.parent - while (parent is KtBinaryExpression && parent.joinable() && parent.lineCount() == nextLineCount) { + while (parent is KtBinaryExpression && parent.joinable() && parent.getLineCount() == lineCount) { binaryExpr = parent parent = parent.parent } @@ -54,7 +49,7 @@ class JoinToStringTemplateHandler : JoinRawLinesHandlerDelegate { var left = binaryExpr.left while (left is KtBinaryExpression && left.joinable()) { val leftLeft = (left as? KtBinaryExpression)?.left ?: break - if (leftLeft.lineCount() < lineCount) break + if (leftLeft.getLineCount() < lineCount - 1) break rightText = ConvertToStringTemplateIntention.buildText(left.right, false) + rightText left = left.left } diff --git a/idea/src/org/jetbrains/kotlin/idea/parameterInfo/LambdaReturnValueHints.kt b/idea/src/org/jetbrains/kotlin/idea/parameterInfo/LambdaReturnValueHints.kt index 3dc88762d05..52442532f9e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/parameterInfo/LambdaReturnValueHints.kt +++ b/idea/src/org/jetbrains/kotlin/idea/parameterInfo/LambdaReturnValueHints.kt @@ -8,7 +8,7 @@ package org.jetbrains.kotlin.idea.parameterInfo import com.intellij.codeInsight.hints.InlayInfo import com.intellij.psi.PsiWhiteSpace import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.isOneLiner +import org.jetbrains.kotlin.idea.core.util.isOneLiner import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType diff --git a/idea/src/org/jetbrains/kotlin/idea/parameterInfo/TypeHints.kt b/idea/src/org/jetbrains/kotlin/idea/parameterInfo/TypeHints.kt index fe72017e3b6..e510e61bc8c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/parameterInfo/TypeHints.kt +++ b/idea/src/org/jetbrains/kotlin/idea/parameterInfo/TypeHints.kt @@ -14,8 +14,9 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings +import org.jetbrains.kotlin.idea.core.util.getLineCount +import org.jetbrains.kotlin.idea.core.util.isMultiLine import org.jetbrains.kotlin.idea.intentions.SpecifyTypeExplicitlyIntention -import org.jetbrains.kotlin.idea.intentions.branchedTransformations.lineCount import org.jetbrains.kotlin.idea.refactoring.getLineNumber import org.jetbrains.kotlin.idea.references.resolveMainReferenceToDescriptors import org.jetbrains.kotlin.idea.util.getResolutionScope @@ -104,7 +105,7 @@ fun provideTypeHint(element: KtCallableDeclaration, offset: Int): List 1) { + if (element is KtProperty && element.isLocal && type.isUnit() && element.isMultiLine()) { val propertyLine = element.getLineNumber() val equalsTokenLine = element.equalsToken?.getLineNumber() ?: -1 val initializerLine = element.initializer?.getLineNumber() ?: -1 diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractorUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractorUtil.kt index 42ee9765153..75af0003f99 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractorUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/extractorUtil.kt @@ -603,7 +603,7 @@ fun ExtractionGeneratorConfiguration.generateDeclaration( val bodyExpression = body.statements.singleOrNull() val bodyOwner = body.parent as KtDeclarationWithBody val useExpressionBodyInspection = UseExpressionBodyInspection() - if (bodyExpression != null && !bodyExpression.isMultiLine() && useExpressionBodyInspection.isActiveFor(bodyOwner)) { + if (bodyExpression != null && useExpressionBodyInspection.isActiveFor(bodyOwner)) { useExpressionBodyInspection.simplify(bodyOwner, !useExplicitReturnType()) } } diff --git a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt.after b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt.after index dd8d090017b..702de22afe9 100644 --- a/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt.after +++ b/idea/testData/refactoring/extractFunction/controlFlow/evaluateExpression/evalWhenExpr.kt.after @@ -8,10 +8,8 @@ fun foo(a: Int): Int { return i(a, b) } -private fun i(a: Int, b: Int): Int { - return when (a + b) { - 0 -> b - 1 -> -b - else -> a - b - } +private fun i(a: Int, b: Int) = when (a + b) { + 0 -> b + 1 -> -b + else -> a - b } \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/multipleTypes2.kt.after b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/multipleTypes2.kt.after index cf9094e007f..f2ec9237c12 100644 --- a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/multipleTypes2.kt.after +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/multipleTypes2.kt.after @@ -18,11 +18,9 @@ fun foo(o: Any) { val x = i(o) } -private fun i(o: Any): Int { - return when (o) { - is A -> { - if (o is T) o.a + o.t else o.a - } - else -> o.hashCode() +private fun i(o: Any) = when (o) { + is A -> { + if (o is T) o.a + o.t else o.a } + else -> o.hashCode() } \ No newline at end of file