From d138577fe1ec583897c14f6a50400aef72d7de8e Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 1 Feb 2018 13:37:21 +0300 Subject: [PATCH] last resource delete from try-with-resources(IDEA-145803) ensure that psi remain correct, automatically resolve conflict with variables declared after the try-with-resources stmt --- .../quickfix/AccessStaticViaInstanceFix.java | 2 +- .../quickfix/DeleteSideEffectsAwareFix.java | 2 +- .../SimplifyBooleanExpressionFix.java | 3 +- .../codeInspection/MakeVoidQuickFix.java | 2 +- .../ObviousNullCheckInspection.java | 6 +- .../codeInspection/RemoveInitializerFix.java | 2 +- .../com/intellij/codeInsight}/BlockUtils.java | 101 ++++++++++++++++-- .../source/tree/java/PsiTryStatementImpl.java | 11 +- .../inlineLocal/ResourceVariable.java.after | 4 +- .../safeDelete/LastResourceVariable.java | 8 +- .../LastResourceVariableConflictingVar.java | 10 ++ ...tResourceVariableConflictingVar_after.java | 10 ++ .../LastResourceVariable_after.java | 6 +- .../java/refactoring/SafeDeleteTest.java | 5 + .../ForLoopReplaceableByWhileInspection.java | 2 +- ...tementWithIdenticalBranchesInspection.java | 1 + .../siyeh/ig/fixes/DeleteCatchSectionFix.java | 51 +-------- .../StringConcatenationInLoopsInspection.java | 1 + .../ig/psiutils/DeclarationSearchUtils.java | 47 -------- ...lFlowStatementWithoutBracesInspection.java | 2 +- .../UnnecessaryBlockStatementInspection.java | 4 +- .../WhileLoopSpinsOnFieldInspection.java | 2 +- ...alFunctionalExpressionUsageInspection.java | 1 + .../PointlessBooleanExpressionInspection.java | 1 + .../ExtractParameterAsLocalVariableFix.java | 2 +- .../RedundantStringOperationInspection.java | 1 + .../ConvertCatchToThrowsIntention.java | 4 +- ...leLoopConditionToIfStatementIntention.java | 2 +- 28 files changed, 162 insertions(+), 131 deletions(-) rename {plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils => java/java-psi-impl/src/com/intellij/codeInsight}/BlockUtils.java (53%) create mode 100644 java/java-tests/testData/refactoring/safeDelete/LastResourceVariableConflictingVar.java create mode 100644 java/java-tests/testData/refactoring/safeDelete/LastResourceVariableConflictingVar_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AccessStaticViaInstanceFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AccessStaticViaInstanceFix.java index 98b5914a61b7..bf3786b145a5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AccessStaticViaInstanceFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AccessStaticViaInstanceFix.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.daemon.impl.quickfix; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.daemon.impl.analysis.HighlightMessageUtil; @@ -32,7 +33,6 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.*; import com.intellij.util.IncorrectOperationException; -import com.siyeh.ig.psiutils.BlockUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteSideEffectsAwareFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteSideEffectsAwareFix.java index 80018c527d60..7b76d08daea2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteSideEffectsAwareFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DeleteSideEffectsAwareFix.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.daemon.impl.quickfix; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.intention.LowPriorityAction; import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement; @@ -23,7 +24,6 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; -import com.siyeh.ig.psiutils.BlockUtils; import com.siyeh.ig.psiutils.SideEffectChecker; import com.siyeh.ig.psiutils.StatementExtractor; import org.jetbrains.annotations.Nls; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java index b002325c0936..3cefc651db1a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java @@ -2,6 +2,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil; import com.intellij.codeInspection.LocalQuickFixOnPsiElement; @@ -219,7 +220,7 @@ public class SimplifyBooleanExpressionFix extends LocalQuickFixOnPsiElement { if (parent instanceof PsiCodeBlock) { if (statement instanceof PsiBlockStatement && - !DeclarationSearchUtils.containsConflictingDeclarations(((PsiBlockStatement)statement).getCodeBlock(), (PsiCodeBlock)parent)) { + !BlockUtils.containsConflictingDeclarations(((PsiBlockStatement)statement).getCodeBlock(), (PsiCodeBlock)parent)) { inlineBlockStatements(orig, (PsiBlockStatement)statement, parent); return; } diff --git a/java/java-impl/src/com/intellij/codeInspection/MakeVoidQuickFix.java b/java/java-impl/src/com/intellij/codeInspection/MakeVoidQuickFix.java index d8e8f65b0237..a96c122a872e 100644 --- a/java/java-impl/src/com/intellij/codeInspection/MakeVoidQuickFix.java +++ b/java/java-impl/src/com/intellij/codeInspection/MakeVoidQuickFix.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInspection; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInspection.reference.RefElement; import com.intellij.codeInspection.reference.RefMethod; @@ -31,7 +32,6 @@ import com.intellij.refactoring.changeSignature.ParameterInfoImpl; import com.intellij.util.IncorrectOperationException; import com.intellij.util.SmartList; import com.siyeh.ig.controlflow.UnnecessaryReturnInspection; -import com.siyeh.ig.psiutils.BlockUtils; import com.siyeh.ig.psiutils.SideEffectChecker; import com.siyeh.ig.psiutils.StatementExtractor; import org.jetbrains.annotations.NotNull; diff --git a/java/java-impl/src/com/intellij/codeInspection/ObviousNullCheckInspection.java b/java/java-impl/src/com/intellij/codeInspection/ObviousNullCheckInspection.java index 8ceae2dc5af8..2bed6d4938dc 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ObviousNullCheckInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/ObviousNullCheckInspection.java @@ -1,6 +1,7 @@ // Copyright 2000-2017 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. package com.intellij.codeInspection; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer; import com.intellij.codeInspection.dataFlow.MethodContract; import com.intellij.codeInspection.dataFlow.StandardMethodContract; @@ -10,7 +11,10 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ObjectUtils; import com.siyeh.ig.callMatcher.CallMatcher; -import com.siyeh.ig.psiutils.*; +import com.siyeh.ig.psiutils.CommentTracker; +import com.siyeh.ig.psiutils.ExpressionUtils; +import com.siyeh.ig.psiutils.SideEffectChecker; +import com.siyeh.ig.psiutils.StatementExtractor; import one.util.streamex.StreamEx; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; diff --git a/java/java-impl/src/com/intellij/codeInspection/RemoveInitializerFix.java b/java/java-impl/src/com/intellij/codeInspection/RemoveInitializerFix.java index 1e0c9ef750f0..cd1adb1ca0b4 100644 --- a/java/java-impl/src/com/intellij/codeInspection/RemoveInitializerFix.java +++ b/java/java-impl/src/com/intellij/codeInspection/RemoveInitializerFix.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInspection; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableFix; import com.intellij.codeInsight.daemon.impl.quickfix.RemoveUnusedVariableUtil; @@ -25,7 +26,6 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiExpressionTrimRenderer; import com.intellij.psi.util.PsiUtil; -import com.siyeh.ig.psiutils.BlockUtils; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/BlockUtils.java b/java/java-psi-impl/src/com/intellij/codeInsight/BlockUtils.java similarity index 53% rename from plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/BlockUtils.java rename to java/java-psi-impl/src/com/intellij/codeInsight/BlockUtils.java index 429d1045414f..0634c987ffee 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/BlockUtils.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/BlockUtils.java @@ -1,16 +1,15 @@ -/* - * 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. - */ -package com.siyeh.ig.psiutils; +// 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. +package com.intellij.codeInsight; +import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/** - * @author Tagir Valeev - */ +import java.util.List; + public class BlockUtils { /** @@ -110,4 +109,92 @@ public class BlockUtils { } throw new AssertionError("can't get body from " + element); } + + public static void unwrapTryBlock(PsiTryStatement tryStatement) { + PsiCodeBlock tryBlock = tryStatement.getTryBlock(); + if (tryBlock == null) { + return; + } + final PsiElement parent = tryStatement.getParent(); + boolean singleStatement = false; + if (parent instanceof PsiStatement) { + final PsiStatement[] statements = tryBlock.getStatements(); + if (statements.length == 1 && !(statements[0] instanceof PsiDeclarationStatement)) { + singleStatement = true; + } + else { + tryStatement = expandSingleStatementToBlockStatement(tryStatement); + } + } + else if (parent instanceof PsiCodeBlock) { + if (containsConflictingDeclarations(tryBlock, (PsiCodeBlock)parent)) { + tryStatement = expandSingleStatementToBlockStatement(tryStatement); + } + } + else { + return; + } + + tryBlock = tryStatement.getTryBlock(); + assert tryBlock != null; + final PsiElement first = singleStatement ? skip(tryBlock.getFirstBodyElement(), true) : tryBlock.getFirstBodyElement(); + final PsiElement last = singleStatement? skip(tryBlock.getLastBodyElement(), false) : tryBlock.getLastBodyElement(); + assert first != null && last != null; + tryStatement.getParent().addRangeBefore(first, last, tryStatement); + tryStatement.delete(); + } + + private static PsiElement skip(PsiElement element, boolean forward) { + if (!(element instanceof PsiWhiteSpace)) { + return element; + } + return forward ? element.getNextSibling() : element.getPrevSibling(); + } + + public static boolean containsConflictingDeclarations(PsiCodeBlock block, PsiCodeBlock parentBlock) { + final PsiStatement[] statements = block.getStatements(); + if (statements.length == 0) { + return false; + } + final int endOffset = block.getTextRange().getEndOffset(); + final List affectedBlocks = + SyntaxTraverser.psiTraverser(parentBlock) + .filter(PsiCodeBlock.class) + .filter(cb -> cb.getTextRange().getEndOffset() > endOffset) + .addAllTo(new SmartList<>()); + final Project project = block.getProject(); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + final PsiResolveHelper resolveHelper = facade.getResolveHelper(); + for (final PsiStatement statement : statements) { + if (!(statement instanceof PsiDeclarationStatement)) { + continue; + } + final PsiDeclarationStatement declaration = (PsiDeclarationStatement)statement; + final PsiElement[] variables = declaration.getDeclaredElements(); + for (PsiElement variable : variables) { + if (!(variable instanceof PsiLocalVariable)) { + continue; + } + final PsiLocalVariable localVariable = (PsiLocalVariable)variable; + final String variableName = localVariable.getName(); + if (variableName == null) { + continue; + } + for (PsiCodeBlock codeBlock : affectedBlocks) { + final PsiVariable target = resolveHelper.resolveAccessibleReferencedVariable(variableName, codeBlock); + if (target instanceof PsiLocalVariable) { + return true; + } + if (target instanceof PsiField) { + for (PsiCodeBlock affectedBlock : affectedBlocks) { + if (!SyntaxTraverser.psiTraverser(affectedBlock).filter(PsiReferenceExpression.class).filter(ref -> ref.resolve() == target).isEmpty()) { + return true; + } + } + } + } + } + } + return false; + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java index 12205a8b56a9..d44ed54665d4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiTryStatementImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.psi.impl.source.tree.java; +import com.intellij.codeInsight.BlockUtils; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; @@ -186,15 +187,7 @@ public class PsiTryStatementImpl extends CompositePsiElement implements PsiTrySt if (child.getPsi() instanceof PsiResourceList && getCatchBlocks().length == 0 && getFinallyBlock() == null) { final PsiCodeBlock tryBlock = getTryBlock(); if (tryBlock != null) { - final PsiCodeBlock block = (PsiCodeBlock)replace(tryBlock); - final PsiJavaToken lBrace = block.getLBrace(); - final PsiJavaToken rBrace = block.getRBrace(); - if (lBrace != null) { - lBrace.delete(); - } - if (rBrace != null) { - rBrace.delete(); - } + BlockUtils.unwrapTryBlock(this); return; } } diff --git a/java/java-tests/testData/refactoring/inlineLocal/ResourceVariable.java.after b/java/java-tests/testData/refactoring/inlineLocal/ResourceVariable.java.after index 0ec390651032..98ed0bc6c743 100644 --- a/java/java-tests/testData/refactoring/inlineLocal/ResourceVariable.java.after +++ b/java/java-tests/testData/refactoring/inlineLocal/ResourceVariable.java.after @@ -1,7 +1,7 @@ class Test { void m() throws Exception { try (AutoCloseable r2 = null) { - System.out.println(null + ", " + r2); - } + System.out.println(null + ", " + r2); + } } } \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable.java b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable.java index 9fed10588243..c2290ad479cb 100644 --- a/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable.java +++ b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable.java @@ -1,6 +1,8 @@ class ARM { - void f() { - try (AutoCloseable r = null) { + void f() { + System.out.println("before"); + try (AutoCloseable r = null) { + System.out.println("inside"); + } } - } } \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableConflictingVar.java b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableConflictingVar.java new file mode 100644 index 000000000000..8c40fdf421d0 --- /dev/null +++ b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableConflictingVar.java @@ -0,0 +1,10 @@ +class ARM { + void f() { + System.out.println("before"); + try (AutoCloseable r = null) { + int i = 0; + System.out.println("inside"); + } + int i = 0; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableConflictingVar_after.java b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableConflictingVar_after.java new file mode 100644 index 000000000000..4bc9fd8b1aa4 --- /dev/null +++ b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariableConflictingVar_after.java @@ -0,0 +1,10 @@ +class ARM { + void f() { + System.out.println("before"); + { + int i = 0; + System.out.println("inside"); + } + int i = 0; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable_after.java b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable_after.java index 3b503678a010..57d234033d27 100644 --- a/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable_after.java +++ b/java/java-tests/testData/refactoring/safeDelete/LastResourceVariable_after.java @@ -1,4 +1,6 @@ class ARM { - void f() { - } + void f() { + System.out.println("before"); + System.out.println("inside"); + } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/SafeDeleteTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/SafeDeleteTest.java index 3a81b8c00407..77749f1ac69a 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/SafeDeleteTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/SafeDeleteTest.java @@ -273,6 +273,11 @@ public class SafeDeleteTest extends MultiFileTestCase { LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7); doSingleFileTest(); } + + public void testLastResourceVariableConflictingVar() throws Exception { + LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7); + doSingleFileTest(); + } public void testLastResourceVariableWithFinallyBlock() throws Exception { LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java index 423178b2da3f..c83512615dd1 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.controlflow; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; @@ -26,7 +27,6 @@ import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; -import com.siyeh.ig.psiutils.BlockUtils; import com.siyeh.ig.psiutils.CommentTracker; import org.jdom.Element; import org.jetbrains.annotations.NotNull; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java index fc4ebdf66aa9..a059fb4abbc5 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.controlflow; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInspection.*; import com.intellij.openapi.project.Project; import com.intellij.psi.*; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteCatchSectionFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteCatchSectionFix.java index 1642b31ccd59..0320681408b3 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteCatchSectionFix.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteCatchSectionFix.java @@ -3,14 +3,14 @@ */ package com.siyeh.ig.fixes; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.PsiCatchSection; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiParameter; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.InspectionGadgetsFix; -import com.siyeh.ig.psiutils.BlockUtils; -import com.siyeh.ig.psiutils.DeclarationSearchUtils; import org.jetbrains.annotations.NotNull; /** @@ -55,51 +55,10 @@ public class DeleteCatchSectionFix extends InspectionGadgetsFix { } final PsiCatchSection catchSection = (PsiCatchSection)grandParent; if (removeTryCatch) { - unwrapTryBlock(catchSection.getTryStatement()); + BlockUtils.unwrapTryBlock(catchSection.getTryStatement()); } else { catchSection.delete(); } } - - public static void unwrapTryBlock(PsiTryStatement tryStatement) { - PsiCodeBlock tryBlock = tryStatement.getTryBlock(); - if (tryBlock == null) { - return; - } - final PsiElement parent = tryStatement.getParent(); - boolean singleStatement = false; - if (parent instanceof PsiStatement) { - final PsiStatement[] statements = tryBlock.getStatements(); - if (statements.length == 1 && !(statements[0] instanceof PsiDeclarationStatement)) { - singleStatement = true; - } - else { - tryStatement = BlockUtils.expandSingleStatementToBlockStatement(tryStatement); - } - } - else if (parent instanceof PsiCodeBlock) { - if (DeclarationSearchUtils.containsConflictingDeclarations(tryBlock, (PsiCodeBlock)parent)) { - tryStatement = BlockUtils.expandSingleStatementToBlockStatement(tryStatement); - } - } - else { - return; - } - - tryBlock = tryStatement.getTryBlock(); - assert tryBlock != null; - final PsiElement first = singleStatement ? skip(tryBlock.getFirstBodyElement(), true) : tryBlock.getFirstBodyElement(); - final PsiElement last = singleStatement? skip(tryBlock.getLastBodyElement(), false) : tryBlock.getLastBodyElement(); - assert first != null && last != null; - tryStatement.getParent().addRangeBefore(first, last, tryStatement); - tryStatement.delete(); - } - - private static PsiElement skip(PsiElement element, boolean forward) { - if (!(element instanceof PsiWhiteSpace)) { - return element; - } - return forward ? element.getNextSibling() : element.getPrevSibling(); - } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConcatenationInLoopsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConcatenationInLoopsInspection.java index b177fd621362..8fc8c89954aa 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConcatenationInLoopsInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConcatenationInLoopsInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.performance; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInsight.NullableNotNullManager; import com.intellij.codeInsight.PsiEquivalenceUtil; import com.intellij.codeInspection.ProblemDescriptor; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DeclarationSearchUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DeclarationSearchUtils.java index 94bba1a5f735..27dcfdbddd0f 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DeclarationSearchUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/DeclarationSearchUtils.java @@ -20,17 +20,12 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.controlFlow.DefUseUtil; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.PsiSearchHelper; import com.intellij.psi.search.SearchScope; -import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - public class DeclarationSearchUtils { private DeclarationSearchUtils() {} @@ -48,48 +43,6 @@ public class DeclarationSearchUtils { return target.equals(variable); } - public static boolean containsConflictingDeclarations(PsiCodeBlock block, PsiCodeBlock parentBlock) { - final PsiStatement[] statements = block.getStatements(); - if (statements.length == 0) { - return false; - } - final int endOffset = block.getTextRange().getEndOffset(); - final List affectedBlocks = - SyntaxTraverser.psiTraverser(parentBlock) - .filter(PsiCodeBlock.class) - .filter(cb -> cb.getTextRange().getEndOffset() > endOffset) - .addAllTo(new SmartList<>()); - final SearchScope affectedScope = new LocalSearchScope(affectedBlocks.toArray(PsiElement.EMPTY_ARRAY)); - final Project project = block.getProject(); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); - final PsiResolveHelper resolveHelper = facade.getResolveHelper(); - for (final PsiStatement statement : statements) { - if (!(statement instanceof PsiDeclarationStatement)) { - continue; - } - final PsiDeclarationStatement declaration = (PsiDeclarationStatement)statement; - final PsiElement[] variables = declaration.getDeclaredElements(); - for (PsiElement variable : variables) { - if (!(variable instanceof PsiLocalVariable)) { - continue; - } - final PsiLocalVariable localVariable = (PsiLocalVariable)variable; - final String variableName = localVariable.getName(); - if (variableName == null) { - continue; - } - for (PsiCodeBlock codeBlock : affectedBlocks) { - final PsiVariable target = resolveHelper.resolveAccessibleReferencedVariable(variableName, codeBlock); - if (target instanceof PsiLocalVariable || - target instanceof PsiField && ReferencesSearch.search(target, affectedScope).findFirst() != null) { - return true; - } - } - } - } - return false; - } - public static PsiExpression findDefinition(@NotNull PsiReferenceExpression referenceExpression, @Nullable PsiVariable variable) { if (variable == null) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java index ab628aa80522..0ddf341c522e 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; @@ -25,7 +26,6 @@ import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; -import com.siyeh.ig.psiutils.BlockUtils; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryBlockStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryBlockStatementInspection.java index a8578ee3c529..fa3591ac5d81 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryBlockStatementInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryBlockStatementInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.style; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInspection.CleanupLocalInspectionTool; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; @@ -25,7 +26,6 @@ import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; -import com.siyeh.ig.psiutils.DeclarationSearchUtils; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -121,7 +121,7 @@ public class UnnecessaryBlockStatementInspection extends BaseInspection implemen } final PsiCodeBlock parentBlock = (PsiCodeBlock)parent; if (parentBlock.getStatementCount() > 1 && - DeclarationSearchUtils.containsConflictingDeclarations(codeBlock, parentBlock)) { + BlockUtils.containsConflictingDeclarations(codeBlock, parentBlock)) { return; } registerError(brace); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java index cffe520fec1d..448cfcb2d087 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/WhileLoopSpinsOnFieldInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.threading; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.openapi.project.Project; @@ -29,7 +30,6 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.callMatcher.CallMatcher; -import com.siyeh.ig.psiutils.BlockUtils; import com.siyeh.ig.psiutils.ControlFlowUtils; import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.VariableAccessUtils; diff --git a/plugins/InspectionGadgets/src/com/intellij/codeInspection/TrivialFunctionalExpressionUsageInspection.java b/plugins/InspectionGadgets/src/com/intellij/codeInspection/TrivialFunctionalExpressionUsageInspection.java index a85faee5a17a..772d81157817 100644 --- a/plugins/InspectionGadgets/src/com/intellij/codeInspection/TrivialFunctionalExpressionUsageInspection.java +++ b/plugins/InspectionGadgets/src/com/intellij/codeInspection/TrivialFunctionalExpressionUsageInspection.java @@ -1,6 +1,7 @@ // Copyright 2000-2017 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. package com.intellij.codeInspection; +import com.intellij.codeInsight.BlockUtils; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.search.searches.ReferencesSearch; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java index 0c69d0643093..ceecf5f832c3 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.controlflow; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.openapi.project.Project; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java index e9805b1b80c5..8c4b60fd3d18 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/ExtractParameterAsLocalVariableFix.java @@ -15,6 +15,7 @@ */ package com.siyeh.ig.fixes; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; @@ -26,7 +27,6 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.RefactoringUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.InspectionGadgetsFix; -import com.siyeh.ig.psiutils.BlockUtils; import com.siyeh.ig.psiutils.CommentTracker; import com.siyeh.ig.psiutils.ParenthesesUtils; import com.siyeh.ipp.psiutils.HighlightUtil; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantStringOperationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantStringOperationInspection.java index 60d09b82954a..879c67eca6f1 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantStringOperationInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/redundancy/RedundantStringOperationInspection.java @@ -1,6 +1,7 @@ // Copyright 2000-2017 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. package com.siyeh.ig.redundancy; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInsight.daemon.impl.quickfix.DeleteElementFix; import com.intellij.codeInspection.*; import com.intellij.openapi.project.Project; diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ConvertCatchToThrowsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ConvertCatchToThrowsIntention.java index f500448a0e10..16ea2da3b5c6 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ConvertCatchToThrowsIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ConvertCatchToThrowsIntention.java @@ -15,12 +15,12 @@ */ package com.siyeh.ipp.exceptions; +import com.intellij.codeInsight.BlockUtils; import com.intellij.codeInsight.FileModificationService; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; -import com.siyeh.ig.fixes.DeleteCatchSectionFix; import com.siyeh.ipp.base.Intention; import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NotNull; @@ -69,7 +69,7 @@ public class ConvertCatchToThrowsIntention extends Intention { catchSection.delete(); } else { - DeleteCatchSectionFix.unwrapTryBlock(tryStatement); + BlockUtils.unwrapTryBlock(tryStatement); } }); } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ExtractWhileLoopConditionToIfStatementIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ExtractWhileLoopConditionToIfStatementIntention.java index 7fd9daac6128..5ce9338fcd48 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ExtractWhileLoopConditionToIfStatementIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ExtractWhileLoopConditionToIfStatementIntention.java @@ -15,10 +15,10 @@ */ package com.siyeh.ipp.whileloop; +import com.intellij.codeInsight.BlockUtils; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; -import com.siyeh.ig.psiutils.BlockUtils; import com.siyeh.ig.psiutils.BoolUtils; import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ipp.base.Intention;