mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java, inspection] new inspection "while can be do-while" IDEA-250650
GitOrigin-RevId: bd2bd0053500b98a316330b08481018825e9211f
This commit is contained in:
committed by
intellij-monorepo-bot
parent
4c9dabf404
commit
e5b2194515
@@ -2522,3 +2522,6 @@ inspection.redundant.embedded.expression.message.literal=Redundant embedded lite
|
||||
inspection.redundant.embedded.expression.message.empty=Redundant empty embedded expression
|
||||
inspection.redundant.embedded.expression.fix.family.name=Inline embedded expression
|
||||
auto.closeable.resource.quickfix.preview=Add method <code>{0}</code> to the list of ignored methods
|
||||
inspection.while.can.be.replaced.with.do.while.display.name='while' can be replaced with 'do while'
|
||||
inspection.while.can.be.replaced.with.do.while.message=Replace 'while' with 'do while'
|
||||
inspection.while.can.be.replaced.with.do.while.family.name=Replace 'while' with 'do while'
|
||||
@@ -11,8 +11,6 @@ replace.for.each.loop.with.indexed.for.loop.intention.family.name=Replace for-ea
|
||||
replace.for.each.loop.with.optimized.indexed.for.loop.intention.name=Replace for-each loop with optimized indexed 'for' loop
|
||||
replace.for.each.loop.with.optimized.indexed.for.loop.intention.family.name=Replace for-each loop with optimized indexed for loop
|
||||
replace.for.each.loop.with.iterator.for.loop.intention.family.name=Replace for-each loop with iterator for loop
|
||||
replace.while.loop.with.do.while.loop.intention.name=Replace 'while' loop with 'do while' loop
|
||||
replace.while.loop.with.do.while.loop.intention.family.name=Replace while loop with do while loop
|
||||
replace.do.while.loop.with.while.loop.intention.name=Replace 'do while' loop with 'while' loop
|
||||
replace.do.while.loop.with.while.loop.intention.family.name=Replace do while loop with while loop
|
||||
#expand.boolean.intention.name=Convert to 'if else'
|
||||
|
||||
@@ -776,6 +776,10 @@
|
||||
key="if.can.be.assertion.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.control.flow.issues" enabledByDefault="true" level="INFORMATION"
|
||||
implementationClass="com.siyeh.ig.asserttoif.IfCanBeAssertionInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="WhileCanBeDoWhile" enabledByDefault="true" level="WEAK WARNING"
|
||||
bundle="messages.InspectionGadgetsBundle" key="inspection.while.can.be.replaced.with.do.while.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.control.flow.issues"
|
||||
implementationClass="com.siyeh.ig.whileloop.WhileCanBeDoWhileInspection"/>
|
||||
|
||||
<!--group.names.data.flow.issues-->
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="BooleanVariableAlwaysNegated" bundle="messages.InspectionGadgetsBundle"
|
||||
|
||||
@@ -254,12 +254,6 @@
|
||||
<bundleName>messages.JavaBundle</bundleName>
|
||||
<categoryKey>intention.category.control.flow</categoryKey>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<language>JAVA</language>
|
||||
<className>com.siyeh.ipp.whileloop.ReplaceWhileLoopWithDoWhileLoopIntention</className>
|
||||
<bundleName>messages.JavaBundle</bundleName>
|
||||
<categoryKey>intention.category.control.flow</categoryKey>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<language>JAVA</language>
|
||||
<className>com.siyeh.ipp.whileloop.ReplaceDoWhileLoopWithWhileLoopIntention</className>
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.siyeh.ig.whileloop;
|
||||
|
||||
import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.modcommand.ModPsiUpdater;
|
||||
import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import com.siyeh.ig.psiutils.BoolUtils;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import com.siyeh.ig.psiutils.EquivalenceChecker;
|
||||
import com.siyeh.ig.psiutils.TrackingEquivalenceChecker;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.intellij.psi.JavaTokenType.WHILE_KEYWORD;
|
||||
|
||||
public class WhileCanBeDoWhileInspection extends AbstractBaseJavaLocalInspectionTool {
|
||||
@Override
|
||||
public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
return new JavaElementVisitor() {
|
||||
@Override
|
||||
public void visitWhileStatement(@NotNull PsiWhileStatement statement) {
|
||||
final PsiStatement body = statement.getBody();
|
||||
final PsiExpression condition = statement.getCondition();
|
||||
if (condition == null) return;
|
||||
|
||||
PsiElement highlightElement = statement.getFirstChild();
|
||||
while (highlightElement != null && highlightElement.getNode().getElementType() != WHILE_KEYWORD) {
|
||||
highlightElement = highlightElement.getNextSibling();
|
||||
}
|
||||
highlightElement = highlightElement != null ? highlightElement : condition;
|
||||
|
||||
final DiffRange duplicateElements;
|
||||
if (body != null) {
|
||||
final Block bodyBlock = Block.init(body);
|
||||
duplicateElements = bodyBlock.getDiffRange(Block.find(statement, bodyBlock.statements.size()));
|
||||
}
|
||||
else {
|
||||
duplicateElements = null;
|
||||
}
|
||||
if (duplicateElements != null) {
|
||||
holder.registerProblem(highlightElement,
|
||||
InspectionGadgetsBundle.message("inspection.while.can.be.replaced.with.do.while.message"),
|
||||
duplicateElements.type(), new ReplaceWhileWithDoWhileFix());
|
||||
}
|
||||
else {
|
||||
holder.registerProblem(highlightElement,
|
||||
InspectionGadgetsBundle.message("inspection.while.can.be.replaced.with.do.while.message"),
|
||||
ProblemHighlightType.INFORMATION, new ReplaceWhileWithDoWhileFix());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class ReplaceWhileWithDoWhileFix extends PsiUpdateModCommandQuickFix {
|
||||
|
||||
@Override
|
||||
public @NotNull String getFamilyName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"inspection.while.can.be.replaced.with.do.while.family.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyFix(@NotNull Project project, @NotNull PsiElement element, @NotNull ModPsiUpdater updater) {
|
||||
final PsiWhileStatement statement = (PsiWhileStatement)element.getParent();
|
||||
if (statement == null) return;
|
||||
|
||||
final PsiStatement body = statement.getBody();
|
||||
final PsiExpression condition = statement.getCondition();
|
||||
final boolean infiniteLoop = BoolUtils.isTrue(condition);
|
||||
|
||||
final DiffRange duplicateElements;
|
||||
if (body != null) {
|
||||
final Block bodyBlock = Block.init(body);
|
||||
duplicateElements = bodyBlock.getDiffRange(Block.find(statement, bodyBlock.statements.size()));
|
||||
}
|
||||
else {
|
||||
duplicateElements = null;
|
||||
}
|
||||
final StringBuilder result = new StringBuilder();
|
||||
final CommentTracker tracker = new CommentTracker();
|
||||
if (!infiniteLoop && duplicateElements == null) {
|
||||
result.append("if(");
|
||||
if (condition != null) {
|
||||
result.append(tracker.text(condition));
|
||||
}
|
||||
result.append(") {\n");
|
||||
}
|
||||
if (body instanceof PsiBlockStatement blockStatement) {
|
||||
result.append("do {");
|
||||
final PsiCodeBlock codeBlock = blockStatement.getCodeBlock();
|
||||
final PsiElement[] children = codeBlock.getChildren();
|
||||
if (children.length > 2) {
|
||||
for (int i = 1; i < children.length - 1; i++) {
|
||||
final PsiElement child = children[i];
|
||||
result.append(tracker.text(child));
|
||||
}
|
||||
}
|
||||
result.append('}');
|
||||
}
|
||||
else if (body != null) {
|
||||
result.append("do ").append(tracker.text(body)).append('\n');
|
||||
}
|
||||
result.append("while(");
|
||||
if (condition != null) {
|
||||
result.append(tracker.text(condition));
|
||||
}
|
||||
result.append(");");
|
||||
if (!infiniteLoop && duplicateElements == null) {
|
||||
result.append("\n}");
|
||||
}
|
||||
|
||||
if (duplicateElements != null) {
|
||||
statement.getParent().deleteChildRange(duplicateElements.first(), duplicateElements.last());
|
||||
}
|
||||
PsiReplacementUtil.replaceStatement(statement, result.toString(), tracker);
|
||||
}
|
||||
}
|
||||
|
||||
private record DiffRange(@NotNull PsiElement first, @NotNull PsiElement last, @NotNull ProblemHighlightType type) {
|
||||
}
|
||||
|
||||
private static class Block {
|
||||
private @NotNull final List<PsiStatement> statements;
|
||||
private @NotNull final List<PsiComment> comments;
|
||||
private final @Nullable PsiStatement block;
|
||||
|
||||
Block(@NotNull PsiBlockStatement block) {
|
||||
this.block = block;
|
||||
comments = new ArrayList<>();
|
||||
statements = new ArrayList<>();
|
||||
for (PsiElement element : block.getCodeBlock().getChildren()) {
|
||||
if (element instanceof PsiComment comment) {
|
||||
comments.add(comment);
|
||||
}
|
||||
else if (element instanceof PsiStatement statement) {
|
||||
statements.add(statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Block(@NotNull List<PsiStatement> statements, @NotNull List<PsiComment> comments) {
|
||||
this.statements = statements;
|
||||
this.comments = comments;
|
||||
this.block = null;
|
||||
}
|
||||
|
||||
static Block init(@NotNull PsiStatement body) {
|
||||
if (body instanceof PsiBlockStatement block) {
|
||||
return new Block(block);
|
||||
}
|
||||
else {
|
||||
return new Block(Collections.singletonList(body), Collections.emptyList());
|
||||
}
|
||||
}
|
||||
|
||||
static Block find(@NotNull PsiElement start, int maxSize) {
|
||||
final List<PsiStatement> statements = new ArrayList<>(maxSize);
|
||||
final List<PsiComment> comments = new ArrayList<>();
|
||||
while (statements.size() < maxSize && (start = start.getPrevSibling()) != null) {
|
||||
if (start instanceof PsiStatement statement) {
|
||||
if (statements.isEmpty() && statement instanceof PsiBlockStatement block) {
|
||||
return new Block(block);
|
||||
}
|
||||
else {
|
||||
statements.add(statement);
|
||||
}
|
||||
}
|
||||
else if (!statements.isEmpty() && start instanceof PsiComment comment) { // ignore comments between while and duplicate code
|
||||
comments.add(comment);
|
||||
}
|
||||
}
|
||||
Collections.reverse(statements);
|
||||
Collections.reverse(comments);
|
||||
return new Block(statements, comments);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
DiffRange getDiffRange(@NotNull Block block) {
|
||||
final EquivalenceChecker checker = new BreakTrackingEquivalenceChecker();
|
||||
if (block.block != null && this.block != null) {
|
||||
if (checker.statementsAreEquivalent(block.block, this.block)) {
|
||||
return new DiffRange(block.block, block.block, equalsComments(comments, block.comments)
|
||||
? ProblemHighlightType.WEAK_WARNING
|
||||
: ProblemHighlightType.INFORMATION);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (statements.size() != block.statements.size()) return null;
|
||||
for (int i = 0; i < statements.size(); i++) {
|
||||
if (!checker.statementsAreEquivalent(statements.get(i), block.statements.get(i))) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new DiffRange(block.statements.get(0), block.statements.get(block.statements.size() - 1),
|
||||
equalsComments(comments, block.comments)
|
||||
? ProblemHighlightType.WEAK_WARNING
|
||||
: ProblemHighlightType.INFORMATION);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean equalsComments(@NotNull List<PsiComment> comments1, @NotNull List<PsiComment> comments2) {
|
||||
if (comments1.size() != comments2.size()) return false;
|
||||
for (int i = 0; i < comments1.size(); i++) {
|
||||
if (!Objects.equals(comments1.get(i).getText().trim(),
|
||||
comments2.get(i).getText().trim())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expanding the possibilities of comparing break statements to avoid the situation:
|
||||
* <pre><code>
|
||||
* while(a) {
|
||||
* if(foo()) break;
|
||||
* while(b) {
|
||||
* if(foo()) break;
|
||||
* }
|
||||
* }
|
||||
* </code></pre>
|
||||
* it isn't equivalent to:
|
||||
* <pre><code>
|
||||
* do(a) {
|
||||
* if(foo()) break;
|
||||
* }
|
||||
* </code></pre>
|
||||
*/
|
||||
private static class BreakTrackingEquivalenceChecker extends TrackingEquivalenceChecker {
|
||||
@Override
|
||||
protected Match breakStatementsMatch(@NotNull PsiBreakStatement statement1, @NotNull PsiBreakStatement statement2) {
|
||||
return !isParentFor(getFirstLoop(statement1), getFirstLoop(statement2))
|
||||
? super.breakStatementsMatch(statement1, statement2)
|
||||
: EXACT_MISMATCH;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getFirstLoop(PsiElement element) {
|
||||
while ((element = element.getParent()) != null) {
|
||||
if (element instanceof PsiLoopStatement) return element;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
private static boolean isParentFor(@Nullable PsiElement element1, @Nullable PsiElement element2) {
|
||||
if (element1 == null || element2 == null) return false;
|
||||
if (element1.equals(element2)) return false;
|
||||
|
||||
PsiElement pinedElement1 = element1;
|
||||
while ((element1 = element1.getParent()) != null) {
|
||||
if (element1.equals(element2)) return true;
|
||||
}
|
||||
while ((element2 = element2.getParent()) != null) {
|
||||
if (pinedElement1.equals(element2)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-79
@@ -1,79 +0,0 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.siyeh.ipp.whileloop;
|
||||
|
||||
import com.intellij.codeInspection.util.IntentionName;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import com.siyeh.ig.psiutils.BoolUtils;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import com.siyeh.ipp.base.MCIntention;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class ReplaceWhileLoopWithDoWhileLoopIntention extends MCIntention {
|
||||
|
||||
@Override
|
||||
public @NotNull String getFamilyName() {
|
||||
return IntentionPowerPackBundle.message("replace.while.loop.with.do.while.loop.intention.family.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @IntentionName @NotNull String getTextForElement(@NotNull PsiElement element) {
|
||||
return IntentionPowerPackBundle.message("replace.while.loop.with.do.while.loop.intention.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
protected PsiElementPredicate getElementPredicate() {
|
||||
return new WhileLoopPredicate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processIntention(@NotNull PsiElement element) {
|
||||
final PsiWhileStatement whileStatement = (PsiWhileStatement)element.getParent();
|
||||
if (whileStatement == null) {
|
||||
return;
|
||||
}
|
||||
final PsiStatement body = whileStatement.getBody();
|
||||
final PsiExpression condition = whileStatement.getCondition();
|
||||
final boolean infiniteLoop = BoolUtils.isTrue(condition);
|
||||
@NonNls final StringBuilder doWhileStatementText = new StringBuilder();
|
||||
CommentTracker tracker = new CommentTracker();
|
||||
if (!infiniteLoop) {
|
||||
doWhileStatementText.append("if(");
|
||||
if (condition != null) {
|
||||
doWhileStatementText.append(tracker.text(condition));
|
||||
}
|
||||
doWhileStatementText.append(") {\n");
|
||||
}
|
||||
if (body instanceof PsiBlockStatement blockStatement) {
|
||||
doWhileStatementText.append("do {");
|
||||
final PsiCodeBlock codeBlock = blockStatement.getCodeBlock();
|
||||
final PsiElement[] children = codeBlock.getChildren();
|
||||
if (children.length > 2) {
|
||||
for (int i = 1; i < children.length - 1; i++) {
|
||||
final PsiElement child = children[i];
|
||||
doWhileStatementText.append(tracker.text(child));
|
||||
}
|
||||
}
|
||||
doWhileStatementText.append('}');
|
||||
}
|
||||
else if (body != null) {
|
||||
doWhileStatementText.append("do ").append(tracker.text(body)).append('\n');
|
||||
}
|
||||
doWhileStatementText.append("while(");
|
||||
if (condition != null) {
|
||||
doWhileStatementText.append(tracker.text(condition));
|
||||
}
|
||||
doWhileStatementText.append(");");
|
||||
if (!infiniteLoop) {
|
||||
doWhileStatementText.append("\n}");
|
||||
}
|
||||
PsiReplacementUtil.replaceStatement(whileStatement, doWhileStatementText.toString(), tracker);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>
|
||||
Reports <code>while</code> loops that could be more effectively written as <code>do-while</code> loops.
|
||||
The focus is on cases where the entire body of the <code>while</code> loop is executed before the condition is checked,
|
||||
leading to potential redundancy in code execution.
|
||||
</p>
|
||||
<p><b>Example:</b></p>
|
||||
<pre><code>
|
||||
foo();
|
||||
while (x) {
|
||||
foo();
|
||||
}
|
||||
</code></pre>
|
||||
<p>Can be replaced with:</p>
|
||||
<pre><code>
|
||||
do {
|
||||
foo();
|
||||
} while (x);
|
||||
</code></pre>
|
||||
<!-- tooltip end -->
|
||||
<p>
|
||||
<small>New in 2024.1</small>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
package com.siyeh.ipp.whileloop.replace_while_with_do_while_loop;
|
||||
|
||||
class InfiniteLoop {
|
||||
|
||||
void m() {
|
||||
while<caret>((true)) {
|
||||
System.out.println(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
package com.siyeh.ipp.whileloop.replace_while_with_do_while_loop;
|
||||
|
||||
class InfiniteLoop {
|
||||
|
||||
void m() {
|
||||
do {
|
||||
System.out.println(1);
|
||||
} while ((true));
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
class NoBraces {
|
||||
void m() {
|
||||
while<caret>//after while
|
||||
(b(/*inside call*/)) //before body
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
boolean b() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
class NoBraces {
|
||||
void m() {
|
||||
//after while
|
||||
//before body
|
||||
if (b(/*inside call*/)) {
|
||||
do System.out.println();
|
||||
while (b(/*inside call*/));
|
||||
}
|
||||
}
|
||||
|
||||
boolean b() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-14
@@ -1,14 +0,0 @@
|
||||
package com.siyeh.ipp.whileloop.replace_while_with_do_while_loop;
|
||||
|
||||
class Regular {
|
||||
|
||||
void m() {
|
||||
<caret>while(b()) {
|
||||
System.out.println(1);
|
||||
}
|
||||
}
|
||||
|
||||
boolean b() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-16
@@ -1,16 +0,0 @@
|
||||
package com.siyeh.ipp.whileloop.replace_while_with_do_while_loop;
|
||||
|
||||
class Regular {
|
||||
|
||||
void m() {
|
||||
if (b()) {
|
||||
do {
|
||||
System.out.println(1);
|
||||
} while (b());
|
||||
}
|
||||
}
|
||||
|
||||
boolean b() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.siyeh.ig.whileloop;
|
||||
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class WhileCanBeDoWhileInspectionTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
public void testReplaceSingleStatement() {
|
||||
doTest("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
System.out.println(1);
|
||||
while<caret>(condition()) {
|
||||
System.out.println(1);
|
||||
}
|
||||
}
|
||||
boolean condition() { return true; }
|
||||
}""", """
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
do {
|
||||
System.out.println(1);
|
||||
} while (condition());
|
||||
}
|
||||
boolean condition() { return true; }
|
||||
}""");
|
||||
}
|
||||
|
||||
public void testReplaceSingleStatementWithoutCodeBlock() {
|
||||
doTest("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
System.out.println(1);
|
||||
while<caret>(condition())
|
||||
System.out.println(1);
|
||||
}
|
||||
boolean condition() { return true; }
|
||||
}""", """
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
do System.out.println(1);
|
||||
while (condition());
|
||||
}
|
||||
boolean condition() { return true; }
|
||||
}""");
|
||||
}
|
||||
|
||||
public void testReplaceCodeBlock() {
|
||||
doTest("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
int sum = 0;
|
||||
{
|
||||
sum += 1;
|
||||
print(sum);
|
||||
int a = 2;
|
||||
sum = sum * a;
|
||||
}
|
||||
while<caret>(sum < 100) {
|
||||
sum += 1;
|
||||
print(sum);
|
||||
int b = 2;
|
||||
sum = sum * b;
|
||||
}
|
||||
}
|
||||
void print(int a) {
|
||||
System.out.println(a);
|
||||
}
|
||||
}""", """
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
int sum = 0;
|
||||
do {
|
||||
sum += 1;
|
||||
print(sum);
|
||||
int b = 2;
|
||||
sum = sum * b;
|
||||
} while (sum < 100);
|
||||
}
|
||||
void print(int a) {
|
||||
System.out.println(a);
|
||||
}
|
||||
}""");
|
||||
}
|
||||
|
||||
public void testReplaceCodeWithComments() {
|
||||
doTest("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
int sum = 0;
|
||||
// comment 0
|
||||
sum += 1;
|
||||
// comment 1
|
||||
print(sum);
|
||||
|
||||
int a = 2;
|
||||
|
||||
sum = sum * a;
|
||||
// comment 2
|
||||
while<caret>(sum < 100) {
|
||||
// comment 3
|
||||
sum += 1;
|
||||
print(sum);
|
||||
int b = 2;
|
||||
sum = sum * b;
|
||||
}
|
||||
}
|
||||
void print(int a) {
|
||||
System.out.println(a);
|
||||
}
|
||||
}""", """
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
int sum = 0;
|
||||
// comment 0
|
||||
// comment 2
|
||||
do {
|
||||
// comment 3
|
||||
sum += 1;
|
||||
print(sum);
|
||||
int b = 2;
|
||||
sum = sum * b;
|
||||
} while (sum < 100);
|
||||
}
|
||||
void print(int a) {
|
||||
System.out.println(a);
|
||||
}
|
||||
}""");
|
||||
}
|
||||
|
||||
public void testDifferentBreaks() {
|
||||
doTest("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
for(int i = 0; i < 10; i++) {
|
||||
int j = i;
|
||||
if(condition()) break;
|
||||
j--;
|
||||
while<caret>(j > 4) {
|
||||
if(condition()) break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean condition() { return true; }
|
||||
}""", """
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
for(int i = 0; i < 10; i++) {
|
||||
int j = i;
|
||||
if(condition()) break;
|
||||
j--;
|
||||
if (j > 4) {
|
||||
do {
|
||||
if (condition()) break;
|
||||
j--;
|
||||
} while (j > 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean condition() { return true; }
|
||||
}""");
|
||||
}
|
||||
|
||||
public void testEqBreaks() {
|
||||
doTest("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
for(int i = 0; i < 10; i++) {
|
||||
int j = i;
|
||||
for(int k = 0; k < 2; k++) if(condition()) break;
|
||||
j--;
|
||||
while<caret>(j > 4) {
|
||||
for(int k = 0; k < 2; k++) if(condition()) break;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean condition() { return true; }
|
||||
}""", """
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
for(int i = 0; i < 10; i++) {
|
||||
int j = i;
|
||||
do {
|
||||
for (int k = 0; k < 2; k++) if (condition()) break;
|
||||
j--;
|
||||
} while (j > 4);
|
||||
}
|
||||
}
|
||||
boolean condition() { return true; }
|
||||
}""");
|
||||
}
|
||||
|
||||
public void testTrue() {
|
||||
doTest("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
int sum = 0;
|
||||
sum += 1;
|
||||
System.out.println("sum");
|
||||
while<caret>(true) {
|
||||
sum += 1;
|
||||
System.out.println("sum");
|
||||
}
|
||||
}
|
||||
}""", """
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
int sum = 0;
|
||||
do {
|
||||
sum += 1;
|
||||
System.out.println("sum");
|
||||
} while (true);
|
||||
}
|
||||
}""");
|
||||
}
|
||||
|
||||
public void testInfiniteLoop() {
|
||||
doTest("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
while<caret>((true)) {
|
||||
System.out.println(1);
|
||||
}
|
||||
}
|
||||
}""", """
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
do {
|
||||
System.out.println(1);
|
||||
} while ((true));
|
||||
}
|
||||
}""");
|
||||
}
|
||||
|
||||
public void testNoBraces() {
|
||||
doTest("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
while<caret>//after while
|
||||
(b(/*inside call*/)) //before body
|
||||
System.out.println();
|
||||
}
|
||||
boolean b() { return true; }
|
||||
}""", """
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
//after while
|
||||
//before body
|
||||
if (b(/*inside call*/)) {
|
||||
do System.out.println();
|
||||
while (b(/*inside call*/));
|
||||
}
|
||||
}
|
||||
boolean b() { return true; }
|
||||
}""");
|
||||
}
|
||||
|
||||
public void testRegular() {
|
||||
doTest("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
<caret>while(b()) {
|
||||
System.out.println(1);
|
||||
};
|
||||
}
|
||||
boolean b() { return true; }
|
||||
}""", """
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
if (b()) {
|
||||
do {
|
||||
System.out.println(1);
|
||||
} while (b());
|
||||
}
|
||||
;
|
||||
}
|
||||
boolean b() { return true; }
|
||||
}""");
|
||||
}
|
||||
|
||||
|
||||
public void testDifferentComments() {
|
||||
testHighlighting("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
int sum = 0;
|
||||
sum += 1;
|
||||
// comment 1
|
||||
System.out.println("sum");
|
||||
<info descr="Replace 'while' with 'do while'">while</info>(true) {
|
||||
sum += 1;
|
||||
// comment 2
|
||||
System.out.println("sum");
|
||||
}
|
||||
}
|
||||
}""");
|
||||
}
|
||||
|
||||
public void testEqComments() {
|
||||
testHighlighting("""
|
||||
class DoWhileClass {
|
||||
void test() {
|
||||
int sum = 0;
|
||||
sum += 1;
|
||||
// comment
|
||||
System.out.println("sum");
|
||||
<weak_warning descr="Replace 'while' with 'do while'">while</weak_warning>(true) {
|
||||
sum += 1;
|
||||
// comment
|
||||
System.out.println("sum");
|
||||
}
|
||||
}
|
||||
}""");
|
||||
}
|
||||
|
||||
|
||||
private void doTest(@NotNull @Language("Java") String before, @NotNull @Language("Java") String after) {
|
||||
myFixture.configureByText("DoWhile.java", before);
|
||||
|
||||
myFixture.enableInspections(new WhileCanBeDoWhileInspection());
|
||||
myFixture.launchAction(myFixture.findSingleIntention("Replace 'while' with 'do while'"));
|
||||
|
||||
myFixture.checkResult(after);
|
||||
}
|
||||
|
||||
private void testHighlighting(@NotNull @Language("Java") String code) {
|
||||
myFixture.configureByText("DoWhile.java", code);
|
||||
|
||||
myFixture.enableInspections(new WhileCanBeDoWhileInspection());
|
||||
myFixture.testHighlighting(true, true, true);
|
||||
}
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ipp.whileloop;
|
||||
|
||||
import com.siyeh.IntentionPowerPackBundle;
|
||||
import com.siyeh.ipp.IPPTestCase;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class ReplaceWhileLoopWithDoWhileLoopIntentionTest extends IPPTestCase {
|
||||
|
||||
public void testInfiniteLoop() { doTest(); }
|
||||
public void testRegular() { doTest(); }
|
||||
public void testNoBraces() { doTest(); }
|
||||
|
||||
@Override
|
||||
protected String getRelativePath() {
|
||||
return "whileloop/replace_while_with_do_while_loop";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getIntentionName() {
|
||||
return IntentionPowerPackBundle.message("replace.while.loop.with.do.while.loop.intention.name");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user