diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/diagnosticBased/KotlinUnreachableCodeInspection.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/diagnosticBased/KotlinUnreachableCodeInspection.kt index 348d2a655f30..d34010dfc21a 100644 --- a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/diagnosticBased/KotlinUnreachableCodeInspection.kt +++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/diagnosticBased/KotlinUnreachableCodeInspection.kt @@ -13,6 +13,7 @@ import com.intellij.psi.createSmartPointer import com.intellij.psi.util.startOffset import org.jetbrains.kotlin.analysis.api.KaSession import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KaFirDiagnostic +import org.jetbrains.kotlin.cfg.UnreachableCode import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.codeinsight.api.applicable.inspections.KotlinKtDiagnosticBasedInspectionBase import org.jetbrains.kotlin.idea.codeinsight.api.applicable.inspections.KotlinModCommandQuickFix @@ -23,7 +24,7 @@ import kotlin.reflect.KClass class KotlinUnreachableCodeInspection : KotlinKtDiagnosticBasedInspectionBase() { data class Context( - val unreachable: Collection> + val unreachableElementPointers: Collection> ) override val diagnosticType: KClass @@ -33,45 +34,27 @@ class KotlinUnreachableCodeInspection : KotlinKtDiagnosticBasedInspectionBase range.union(element.textRange) } } - ?: return null + val reachable = diagnostic.reachable.mapNotNullTo(HashSet()) { it as? KtElement } + val unreachable = diagnostic.unreachable.mapNotNullTo(HashSet()) { it as? KtElement } - val unreachableRange = unreachable.fold(firstUnreachable.textRange) { it, element -> it.union(element.textRange) } + val unreachableTextRanges = + UnreachableCode + .getUnreachableTextRanges(element, reachable, unreachable) + .ifEmpty { return null } - val startOffset = unreachableRange.startOffset - val reachableStartOffset = reachableTextRange.startOffset - - val unreachableTextRange = if (startOffset <= reachableStartOffset) { - TextRange(startOffset, unreachableRange.endOffset.coerceAtMost(reachableStartOffset)) - } else { - TextRange(reachableStartOffset, unreachableRange.endOffset.coerceAtMost(reachableTextRange.endOffset)) + val unreachableElementPointers = buildList { + val startOffset = element.startOffset + for (textRange in unreachableTextRanges) { + var offset = textRange.startOffset - startOffset + while (offset < textRange.endOffset - startOffset) { + val findElementAt = element.findElementAt(offset) ?: break + offset += findElementAt.textLength + this += findElementAt.createSmartPointer() + } } - - calculateUnreachableElements(element, unreachableTextRange, unreachableRange) - } else { - emptyList() } - return Context(unreachableElements) - } - private fun calculateUnreachableElements( - element: KtElement, - unreachableTextRange: TextRange, - singleUnreachableRange: TextRange - ): List> = buildList { - var offset = unreachableTextRange.startOffset - element.startOffset - while (offset < singleUnreachableRange.endOffset - element.startOffset) { - val e = element.findElementAt(offset) ?: break - if (e !is PsiWhiteSpace && unreachableTextRange.contains(e.textRange)) { - this += e.createSmartPointer() - } - offset += e.textRange.length - } + return Context(unreachableElementPointers) } override fun getProblemDescription( @@ -91,14 +74,10 @@ class KotlinUnreachableCodeInspection : KotlinKtDiagnosticBasedInspectionBase e is PsiWhiteSpace }?.let(updater::getWritable) }.forEach(PsiElement::delete) - } } } @@ -118,22 +97,12 @@ class KotlinUnreachableCodeInspection : KotlinKtDiagnosticBasedInspectionBase + val e = pointer.element ?: return@forEach val problemDescriptor = holder.manager.createProblemDescriptor( element, context, - TextRange(0, element.textRange.length), - isOnTheFly, - ) - holder.registerProblem(problemDescriptor) - } else { - val problemDescriptor = holder.manager.createProblemDescriptor( - element, - context, - first.textRange.union(last.textRange).shiftLeft(element.startOffset), + e.textRange.shiftLeft(element.startOffset), isOnTheFly, ) holder.registerProblem(problemDescriptor) diff --git a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java index 1bedabb8cbb6..f42c4a7da9ea 100644 --- a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java +++ b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2LocalInspectionTestGenerated.java @@ -14319,6 +14319,11 @@ public abstract class K2LocalInspectionTestGenerated extends AbstractK2LocalInsp runTest("../../../idea/tests/testData/inspectionsLocal/kotlinUnreachableCode/returnReturn.kt"); } + @TestMetadata("returnReturnAndStatement.kt") + public void testReturnReturnAndStatement() throws Exception { + runTest("../../../idea/tests/testData/inspectionsLocal/kotlinUnreachableCode/returnReturnAndStatement.kt"); + } + @TestMetadata("returnTryReturn.kt") public void testReturnTryReturn() throws Exception { runTest("../../../idea/tests/testData/inspectionsLocal/kotlinUnreachableCode/returnTryReturn.kt"); diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index d49440539ee1..9acd6b09f3ad 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -6971,6 +6971,11 @@ public abstract class LocalInspectionTestGenerated extends AbstractLocalInspecti runTest("testData/inspectionsLocal/kotlinUnreachableCode/returnReturn.kt"); } + @TestMetadata("returnReturnAndStatement.kt") + public void testReturnReturnAndStatement() throws Exception { + runTest("testData/inspectionsLocal/kotlinUnreachableCode/returnReturnAndStatement.kt"); + } + @TestMetadata("returnTryReturn.kt") public void testReturnTryReturn() throws Exception { runTest("testData/inspectionsLocal/kotlinUnreachableCode/returnTryReturn.kt"); diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/kotlinUnreachableCode/returnReturnAndStatement.kt b/plugins/kotlin/idea/tests/testData/inspectionsLocal/kotlinUnreachableCode/returnReturnAndStatement.kt new file mode 100644 index 000000000000..dfe690434720 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/kotlinUnreachableCode/returnReturnAndStatement.kt @@ -0,0 +1,6 @@ +// IGNORE_K1 +// FIX: Remove unreachable code +fun f(): Int { + val x = 1 + return return 42 +} diff --git a/plugins/kotlin/idea/tests/testData/inspectionsLocal/kotlinUnreachableCode/returnReturnAndStatement.kt.after b/plugins/kotlin/idea/tests/testData/inspectionsLocal/kotlinUnreachableCode/returnReturnAndStatement.kt.after new file mode 100644 index 000000000000..9689bc60f43e --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspectionsLocal/kotlinUnreachableCode/returnReturnAndStatement.kt.after @@ -0,0 +1,6 @@ +// IGNORE_K1 +// FIX: Remove unreachable code +fun f(): Int { + val x = 1 + return 42 +}