mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Java: fix replacing tail recursion with iteration failure caused by conversion to ModCommand (IDEA-371968)
GitOrigin-RevId: 1d05dc8583221fb8583828847720b07be1d5bdd3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
47854e8b7b
commit
3bf36654d0
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2018 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2025 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -78,22 +78,22 @@ public final class TailRecursionInspection extends BaseInspection implements Cle
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyFix(@NotNull Project project, @NotNull PsiElement tailCallToken, @NotNull ModPsiUpdater updater) {
|
||||
final PsiMethod method =
|
||||
PsiTreeUtil.getParentOfType(tailCallToken, PsiMethod.class, true, PsiClass.class, PsiLambdaExpression.class);
|
||||
protected void applyFix(@NotNull Project project, @NotNull PsiElement element, @NotNull ModPsiUpdater updater) {
|
||||
PsiFile originalFile = updater.getOriginalFile(element.getContainingFile());
|
||||
final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, true, PsiClass.class, PsiLambdaExpression.class);
|
||||
if (method == null) {
|
||||
return;
|
||||
}
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
if (body == null) {
|
||||
PsiMethod originalMethod = PsiTreeUtil.findSameElementInCopy(method, originalFile);
|
||||
final PsiCodeBlock originalBody = originalMethod.getBody();
|
||||
if (originalBody == null) {
|
||||
return;
|
||||
}
|
||||
final @NonNls StringBuilder builder = new StringBuilder();
|
||||
builder.append('{');
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
}
|
||||
final @NonNls StringBuilder builder = new StringBuilder("{");
|
||||
final String thisVariableName;
|
||||
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project);
|
||||
if (methodReturnsContainingClassType(method, containingClass)) {
|
||||
@@ -101,7 +101,7 @@ public final class TailRecursionInspection extends BaseInspection implements Cle
|
||||
thisVariableName = styleManager.suggestUniqueVariableName("result", method, false);
|
||||
builder.append(' ').append(thisVariableName).append(" = this;");
|
||||
}
|
||||
else if (methodContainsCallOnOtherInstance(method)) {
|
||||
else if (methodContainsCallOnOtherInstance(originalMethod)) {
|
||||
builder.append(containingClass.getName());
|
||||
thisVariableName = styleManager.suggestUniqueVariableName("other", method, false);
|
||||
builder.append(' ').append(thisVariableName).append(" = this;");
|
||||
@@ -110,7 +110,7 @@ public final class TailRecursionInspection extends BaseInspection implements Cle
|
||||
thisVariableName = null;
|
||||
}
|
||||
final boolean tailCallIsContainedInLoop;
|
||||
if (ControlFlowUtils.isInLoop(tailCallToken)) {
|
||||
if (ControlFlowUtils.isInLoop(element)) {
|
||||
tailCallIsContainedInLoop = true;
|
||||
builder.append(method.getName()).append(':');
|
||||
}
|
||||
@@ -119,13 +119,15 @@ public final class TailRecursionInspection extends BaseInspection implements Cle
|
||||
}
|
||||
builder.append("while(true)");
|
||||
final boolean methodMayCompleteNormally = ControlFlowUtils.methodMayCompleteNormally(method);
|
||||
replaceTailCalls(body, method, thisVariableName, tailCallIsContainedInLoop, methodMayCompleteNormally, builder);
|
||||
replaceTailCalls(originalBody, originalMethod, thisVariableName, tailCallIsContainedInLoop, methodMayCompleteNormally, builder);
|
||||
if (methodMayCompleteNormally) {
|
||||
builder.insert(builder.length() - 1, "return;");
|
||||
}
|
||||
builder.append('}');
|
||||
final PsiCodeBlock block = JavaPsiFacade.getElementFactory(project).createCodeBlockFromText(builder.toString(), method);
|
||||
removeEmptyElse(block);
|
||||
PsiCodeBlock body = method.getBody();
|
||||
assert body != null;
|
||||
CodeStyleManager.getInstance(project).reformat(body.replace(block));
|
||||
}
|
||||
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
class ClassInOtherFile {
|
||||
private final Container parent;
|
||||
private boolean boundsValid;
|
||||
|
||||
public Visual(Container parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
ClassInOtherFile other = this;
|
||||
while (true) {
|
||||
other.boundsValid = false;
|
||||
if (other.parent != null) {
|
||||
other = other.parent;
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class ClassInOtherFile {
|
||||
private final Container parent;
|
||||
private boolean boundsValid;
|
||||
|
||||
public Visual(Container parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
void invalidate() {
|
||||
boundsValid = false;
|
||||
if (parent != null) {
|
||||
parent.<caret>invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.siyeh.ig.fixes.performance;
|
||||
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
@@ -34,6 +34,18 @@ public class TailRecursionInspectionFixTest extends IGQuickFixesTestCase {
|
||||
public void testVoidMethod1() { doTest(); }
|
||||
public void testVoidMethod2() { doTest(); }
|
||||
public void testAndOrChain() { doTest(); }
|
||||
|
||||
public void testClassInOtherFile() {
|
||||
myFixture.addClass("""
|
||||
class Container extends ClassInOtherFile {
|
||||
Container(Container parent) {
|
||||
super(parent);
|
||||
}
|
||||
}
|
||||
""");
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testAndOrChain2() {
|
||||
CommonCodeStyleSettings settings = CodeStyle.getSettings(getProject()).getCommonSettings(JavaLanguage.INSTANCE);
|
||||
int oldValue = settings.IF_BRACE_FORCE;
|
||||
|
||||
Reference in New Issue
Block a user