[java-refactoring] Handle sub-expression extracting when prefix contains another call

Fixes IDEA-375976 "Extract Method" from selected sub-expression starts editing the wrong place and produces uncompileable code

GitOrigin-RevId: 88b610c8376ff56882052c3a977a465a796cf1d0
This commit is contained in:
Tagir Valeev
2025-07-30 17:13:42 +00:00
committed by intellij-monorepo-bot
parent d19b7f3fa7
commit b9e7976d92
4 changed files with 51 additions and 1 deletions
@@ -26,6 +26,7 @@ import com.intellij.psi.impl.source.codeStyle.JavaCodeStyleManagerImpl
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.util.PsiUtil
import com.intellij.psi.util.parentOfType
import com.intellij.refactoring.IntroduceVariableUtil
import com.intellij.refactoring.extractMethod.newImpl.structures.DataOutput
import com.intellij.refactoring.extractMethod.newImpl.structures.DataOutput.*
@@ -262,7 +263,7 @@ object ExtractMethodHelper {
val targetAsExpression = target.singleOrNull() as? PsiExpression
if (sourceAsExpression != null && targetAsExpression != null) {
val replacedExpression = IntroduceVariableUtil.replace(sourceAsExpression, targetAsExpression, sourceAsExpression.project)
return listOf(replacedExpression)
return listOf(findSubExpression(sourceAsExpression, replacedExpression) ?: replacedExpression)
}
val psiRange = getPhysicalPsiRange(sourceAsExpression) ?: PsiRange(source.first().parent, source.first(), source.last())
val replacedElements = target.reversed().map { statement -> psiRange.lastChild.addSiblingAfter(statement) }.reversed()
@@ -270,6 +271,13 @@ object ExtractMethodHelper {
return replacedElements
}
private fun findSubExpression(sourceAsExpression: PsiExpression, context: PsiElement): PsiExpression? {
val marker = sourceAsExpression.getUserData(ElementToWorkOn.TEXT_RANGE) ?: return null
val file = context.containingFile
return PsiTreeUtil.findCommonParent(file.findElementAt(marker.textRange.startOffset), file.findElementAt(marker.textRange.endOffset - 1))
?.parentOfType<PsiExpression>(withSelf = true)
}
fun replaceWithMethod(targetClass: PsiClass, elements: List<PsiElement>, preparedElements: ExtractedElements): ExtractedElements {
val callElements = preparedElements.callElements
if (callElements.isNotEmpty()) {