From 8c4e0bb450cdbb7a1f38484d89204da6d9c6e78c Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Thu, 10 Nov 2016 19:36:35 +0300 Subject: [PATCH 1/8] IDEA-163825 Smart step variants from another line --- .../debugger/actions/JavaSmartStepIntoHandler.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java index a6f570cbbf78..af67bc2e641f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaSmartStepIntoHandler.java @@ -215,14 +215,14 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler { private void visitConditional(@Nullable PsiElement condition, @Nullable PsiElement thenBranch, @Nullable PsiElement elseBranch) { - if (condition != null) { + if (condition != null && checkTextRange(condition, true)) { condition.accept(this); } ThreeState conditionRes = evaluateCondition(condition); - if (conditionRes != ThreeState.NO && thenBranch != null) { + if (conditionRes != ThreeState.NO && thenBranch != null && checkTextRange(thenBranch, true)) { thenBranch.accept(this); } - if (conditionRes != ThreeState.YES && elseBranch != null) { + if (conditionRes != ThreeState.YES && elseBranch != null && checkTextRange(elseBranch, true)) { elseBranch.accept(this); } } @@ -246,7 +246,7 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler { super.visitExpression(expression); } - boolean checkTextRange(PsiElement expression, boolean expand) { + boolean checkTextRange(@NotNull PsiElement expression, boolean expand) { TextRange range = expression.getTextRange(); if (lineRange.intersects(range)) { if (expand) { From fd89b0ed1881be9fb3a09193adb63aae25a781c7 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Thu, 10 Nov 2016 17:25:29 +0100 Subject: [PATCH 2/8] introduce variable: distinguish lambda parameters but allow param free expressions (IDEA-163785) --- .../IntroduceVariableBase.java | 38 ++++++++++--------- .../DistinguishLambdaParams.after.java | 15 ++++++++ .../DistinguishLambdaParams.java | 14 +++++++ .../refactoring/IntroduceVariableTest.java | 4 ++ 4 files changed, 54 insertions(+), 17 deletions(-) create mode 100644 java/java-tests/testData/refactoring/introduceVariable/DistinguishLambdaParams.after.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/DistinguishLambdaParams.java diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index 3b67150d9a5e..9d2fd531c786 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -750,29 +750,33 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { } private static ExpressionOccurrenceManager createOccurrenceManager(PsiExpression expr, PsiElement tempContainer) { - boolean skipForStatement = true; - final PsiForStatement forStatement = PsiTreeUtil.getParentOfType(expr, PsiForStatement.class); - if (forStatement != null) { - Set vars = new HashSet<>(); - SyntaxTraverser.psiTraverser().withRoot(expr) - .filter(element -> element instanceof PsiReferenceExpression) - .forEach(element -> { - final PsiElement resolve = ((PsiReferenceExpression)element).resolve(); - if (resolve instanceof PsiVariable) { - vars.add((PsiVariable)resolve); - } - }); - skipForStatement = vars.stream().noneMatch(variable -> PsiTreeUtil.isAncestor(forStatement.getInitialization(), variable, true)); - } + Set vars = new HashSet<>(); + SyntaxTraverser.psiTraverser().withRoot(expr) + .filter(element -> element instanceof PsiReferenceExpression) + .forEach(element -> { + final PsiElement resolve = ((PsiReferenceExpression)element).resolve(); + if (resolve instanceof PsiVariable) { + vars.add((PsiVariable)resolve); + } + }); PsiElement containerParent = tempContainer; PsiElement lastScope = tempContainer; while (true) { if (containerParent instanceof PsiFile) break; if (containerParent instanceof PsiMethod) break; - // allow to find occurrences outside lambda as we allow this for loops, ifs, etc - // if (containerParent instanceof PsiLambdaExpression) break; - if (!skipForStatement && containerParent instanceof PsiForStatement) break; + if (containerParent instanceof PsiLambdaExpression) { + PsiParameter[] parameters = ((PsiLambdaExpression)containerParent).getParameterList().getParameters(); + if (Arrays.stream(parameters).anyMatch(parameter -> vars.contains(parameter))) { + break; + } + } + if (containerParent instanceof PsiForStatement) { + PsiForStatement forStatement = (PsiForStatement)containerParent; + if (vars.stream().anyMatch(variable -> PsiTreeUtil.isAncestor(forStatement.getInitialization(), variable, true))) { + break; + } + } containerParent = containerParent.getParent(); if (containerParent instanceof PsiCodeBlock) { lastScope = containerParent; diff --git a/java/java-tests/testData/refactoring/introduceVariable/DistinguishLambdaParams.after.java b/java/java-tests/testData/refactoring/introduceVariable/DistinguishLambdaParams.after.java new file mode 100644 index 000000000000..fb3756447ecf --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/DistinguishLambdaParams.after.java @@ -0,0 +1,15 @@ +import java.util.function.UnaryOperator; + +class Main { + public static void main(String[] args) { + UnaryOperator f1 = s -> { + System.out.println("foo"); + String temp = s.trim(); + return temp; + }; + UnaryOperator f2 = s -> { + System.out.println("foo"); + return s.trim(); + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/DistinguishLambdaParams.java b/java/java-tests/testData/refactoring/introduceVariable/DistinguishLambdaParams.java new file mode 100644 index 000000000000..0307800a9d70 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/DistinguishLambdaParams.java @@ -0,0 +1,14 @@ +import java.util.function.UnaryOperator; + +class Main { + public static void main(String[] args) { + UnaryOperator f1 = s -> { + System.out.println("foo"); + return s.trim(); + }; + UnaryOperator f2 = s -> { + System.out.println("foo"); + return s.trim(); + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java index f7da07c33723..67f74b3d377d 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java @@ -211,6 +211,10 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { doTest(new MockIntroduceVariableHandler("temp", true, false, false, "int")); } + public void testDistinguishLambdaParams() { + doTest(new MockIntroduceVariableHandler("temp", true, false, false, CommonClassNames.JAVA_LANG_STRING)); + } + public void testDuplicateGenericExpressions() { doTest(new MockIntroduceVariableHandler("temp", true, false, false, "Foo2")); } From edc467316a9d63dc83450950003d286487282060 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Thu, 10 Nov 2016 17:45:15 +0100 Subject: [PATCH 3/8] remove empty overrider --- .../deadCode/UnusedDeclarationInspectionBase.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java index 3ed593392863..8d2b4ede119e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java @@ -722,11 +722,6 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool { } } - @Override - public void initialize(@NotNull GlobalInspectionContext context) { - super.initialize(context); - } - @TestOnly public List getExtensions() { return myExtensions; From 616eb7ec4f1b2ac64992e30ef5c7f2d12e36a7fe Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 10 Nov 2016 15:13:41 +0100 Subject: [PATCH 4/8] async console filters: detect line removal earlier, allocate less memory (IDEA-163771) --- .../src/com/intellij/execution/impl/AsyncFilterRunner.java | 6 +++--- .../com/intellij/execution/impl/EditorHyperlinkSupport.java | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/execution/impl/AsyncFilterRunner.java b/platform/platform-impl/src/com/intellij/execution/impl/AsyncFilterRunner.java index 53fa4cd40fc0..fd67e3707f31 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/AsyncFilterRunner.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/AsyncFilterRunner.java @@ -135,7 +135,7 @@ class AsyncFilterRunner { List results = new ArrayList<>(); for (LineHighlighter task : tasks) { ProgressManager.checkCanceled(); - if (!marker.isValid()) return FilterResults.EMPTY; + if (!marker.isValid() || marker.getEndOffset() == 0) return FilterResults.EMPTY; ContainerUtil.addIfNotNull(results, task.compute()); } return new FilterResults(markerOffset, marker, results); @@ -146,8 +146,8 @@ class AsyncFilterRunner { private static LineHighlighter processLine(Document document, Filter filter, int line) { int lineEnd = document.getLineEndOffset(line); int endOffset = lineEnd + (lineEnd < document.getTextLength() ? 1 /* for \n */ : 0); - String text = EditorHyperlinkSupport.getLineText(document, line, true); - return () -> checkRange(filter, endOffset, filter.applyFilter(text, endOffset)); + CharSequence text = EditorHyperlinkSupport.getLineSequence(document, line, true); + return () -> checkRange(filter, endOffset, filter.applyFilter(text.toString(), endOffset)); } private static Filter.Result checkRange(Filter filter, int endOffset, Filter.Result result) { diff --git a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java index 2af4e82824e1..ef17f5400686 100644 --- a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java +++ b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java @@ -371,11 +371,15 @@ public class EditorHyperlinkSupport { @NotNull public static String getLineText(@NotNull Document document, int lineNumber, boolean includeEol) { + return getLineSequence(document, lineNumber, includeEol).toString(); + } + + static CharSequence getLineSequence(@NotNull Document document, int lineNumber, boolean includeEol) { int endOffset = document.getLineEndOffset(lineNumber); if (includeEol && endOffset < document.getTextLength()) { endOffset++; } - return document.getImmutableCharSequence().subSequence(document.getLineStartOffset(lineNumber), endOffset).toString(); + return document.getImmutableCharSequence().subSequence(document.getLineStartOffset(lineNumber), endOffset); } private static class HyperlinkInfoTextAttributes extends TextAttributes { From 88c6ee1eb31c96b2e0ed490dd9ea9bd070058ec3 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 10 Nov 2016 15:28:58 +0100 Subject: [PATCH 5/8] AntChangeContextFix doesn't need write action --- .../com/intellij/lang/ant/quickfix/AntChangeContextFix.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/ant/src/com/intellij/lang/ant/quickfix/AntChangeContextFix.java b/plugins/ant/src/com/intellij/lang/ant/quickfix/AntChangeContextFix.java index 21945f4943d8..415d8faf834c 100644 --- a/plugins/ant/src/com/intellij/lang/ant/quickfix/AntChangeContextFix.java +++ b/plugins/ant/src/com/intellij/lang/ant/quickfix/AntChangeContextFix.java @@ -54,6 +54,11 @@ public class AntChangeContextFix extends BaseIntentionAction { return true; } + @Override + public boolean startInWriteAction() { + return false; + } + public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException { final HectorComponent component = new HectorComponent(file); //final JComponent focusComponent = findComponentToFocus(component); From 4717e7d08e450d142faeead53436dffa19983875 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 10 Nov 2016 16:33:10 +0100 Subject: [PATCH 6/8] remove invalid external annotation entry from Iterable (IDEA-CR-15615) --- java/jdkAnnotations/java/lang/annotations.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/java/jdkAnnotations/java/lang/annotations.xml b/java/jdkAnnotations/java/lang/annotations.xml index 098ef28db6a4..7ce0469d41b8 100644 --- a/java/jdkAnnotations/java/lang/annotations.xml +++ b/java/jdkAnnotations/java/lang/annotations.xml @@ -64,9 +64,6 @@ - - - From e3f78ab7728389410fd3c327b79594a1a95af5b0 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 10 Nov 2016 17:04:32 +0100 Subject: [PATCH 7/8] remove unused PriorityLocalQuickFixWrapper --- .../impl/PriorityLocalQuickFixWrapper.java | 85 ------------------- 1 file changed, 85 deletions(-) delete mode 100644 platform/lang-api/src/com/intellij/codeInsight/intention/impl/PriorityLocalQuickFixWrapper.java diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/impl/PriorityLocalQuickFixWrapper.java b/platform/lang-api/src/com/intellij/codeInsight/intention/impl/PriorityLocalQuickFixWrapper.java deleted file mode 100644 index 67b14a8a8f1c..000000000000 --- a/platform/lang-api/src/com/intellij/codeInsight/intention/impl/PriorityLocalQuickFixWrapper.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2000-2014 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.intellij.codeInsight.intention.impl; - -import com.intellij.codeInsight.intention.HighPriorityAction; -import com.intellij.codeInsight.intention.LowPriorityAction; -import com.intellij.codeInspection.LocalQuickFix; -import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.openapi.project.Project; -import org.jetbrains.annotations.NotNull; - -/** - * @author Danila Ponomarenko - */ -public abstract class PriorityLocalQuickFixWrapper implements LocalQuickFix { - private final LocalQuickFix fix; - - private PriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) { - this.fix = fix; - } - - @NotNull - @Override - public String getName() { - return fix.getName(); - } - - @NotNull - @Override - public String getFamilyName() { - return fix.getFamilyName(); - } - - @Override - public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - fix.applyFix(project, descriptor); - } - - private static class HighPriorityLocalQuickFixWrapper extends PriorityLocalQuickFixWrapper implements HighPriorityAction { - protected HighPriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) { - super(fix); - } - } - - private static class NormalPriorityLocalQuickFixWrapper extends PriorityLocalQuickFixWrapper { - protected NormalPriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) { - super(fix); - } - } - - - private static class LowPriorityLocalQuickFixWrapper extends PriorityLocalQuickFixWrapper implements LowPriorityAction { - protected LowPriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) { - super(fix); - } - } - - @NotNull - public static LocalQuickFix highPriority(@NotNull LocalQuickFix fix) { - return new HighPriorityLocalQuickFixWrapper(fix); - } - - @NotNull - public static LocalQuickFix normalPriority(@NotNull LocalQuickFix fix) { - return new NormalPriorityLocalQuickFixWrapper(fix); - } - - @NotNull - public static LocalQuickFix lowPriority(@NotNull LocalQuickFix fix) { - return new LowPriorityLocalQuickFixWrapper(fix); - } -} From 613c65bda997b58f472a4b559a8dbea08e128a67 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 10 Nov 2016 17:09:33 +0100 Subject: [PATCH 8/8] make some quick fixes not require write action --- .../codeInspection/nullable/ChangeNullableDefaultsFix.java | 5 +++++ .../impl/quickfix/EnableOptimizeImportsOnTheFlyFix.java | 2 +- .../deadCode/UnusedDeclarationPresentation.java | 2 +- .../codeInspection/util/SpecialAnnotationsUtil.java | 6 +++--- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/ChangeNullableDefaultsFix.java b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/ChangeNullableDefaultsFix.java index 237f227c4aa3..c3549dffc93b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/ChangeNullableDefaultsFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/ChangeNullableDefaultsFix.java @@ -49,6 +49,11 @@ class ChangeNullableDefaultsFix implements LocalQuickFix { return "Make \"" + (myNotNullName != null ? myNotNullName : myNullableName) + "\" default annotation"; } + @Override + public boolean startInWriteAction() { + return false; + } + @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { if (myNotNullName != null) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/EnableOptimizeImportsOnTheFlyFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/EnableOptimizeImportsOnTheFlyFix.java index 91e9910e1462..f3ac84cf05bb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/EnableOptimizeImportsOnTheFlyFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/EnableOptimizeImportsOnTheFlyFix.java @@ -55,6 +55,6 @@ public class EnableOptimizeImportsOnTheFlyFix implements IntentionAction, LowPri @Override public boolean startInWriteAction() { - return true; + return false; } } diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java index 1fe7c3b046db..a654116fb20d 100644 --- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java +++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java @@ -619,7 +619,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta @Override public boolean startInWriteAction() { - return true; + return false; } } diff --git a/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java b/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java index ccc0845ec42f..65ab2dd9c422 100644 --- a/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java +++ b/java/java-impl/src/com/intellij/codeInspection/util/SpecialAnnotationsUtil.java @@ -29,13 +29,13 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Condition; -import com.intellij.psi.*; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiFile; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.*; import com.intellij.ui.components.JBList; import com.intellij.util.IconUtil; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.containers.Predicate; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -170,7 +170,7 @@ public class SpecialAnnotationsUtil { @Override public boolean startInWriteAction() { - return true; + return false; } }; }