From 80ad603b6696480c2cec1ef953d2c6bab6218931 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 19 Apr 2016 14:31:40 +0300 Subject: [PATCH 1/9] editor: reduce direct access to myLineToGutterRenderers map --- .../impl/EditorGutterComponentImpl.java | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index adda15ddc1c8..fa805afb9406 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -66,7 +66,7 @@ import com.intellij.util.ui.UIUtil; import gnu.trove.TIntArrayList; import gnu.trove.TIntFunction; import gnu.trove.TIntObjectHashMap; -import gnu.trove.TObjectProcedure; +import gnu.trove.TIntObjectProcedure; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -128,6 +128,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private final EditorImpl myEditor; private final FoldingAnchorsOverlayStrategy myAnchorsDisplayStrategy; + private TIntObjectHashMap> myLineToGutterRenderers; private int myIconsAreaWidth = 0; private int myLineNumberAreaWidth = 0; private int myAdditionalLineNumberAreaWidth = 0; @@ -748,8 +749,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - private TIntObjectHashMap> myLineToGutterRenderers; - private void calcLineMarkerAreaWidth(boolean canShrink) { myLineToGutterRenderers = new TIntObjectHashMap<>(); myLeftFreePaintersAreaShown = myForceLeftFreePaintersAreaShown; @@ -792,21 +791,18 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse myIconsAreaWidth = Math.max(myIconsAreaWidth, myEditor.getLineHeight()); } - myLineToGutterRenderers.forEachValue(new TObjectProcedure>() { - @Override - public boolean execute(List renderers) { - int width = 1; - for (int i = 0; i < renderers.size(); i++) { - GutterMark renderer = renderers.get(i); - if (!checkDumbAware(renderer)) continue; - width += scaleIcon(renderer.getIcon()).getIconWidth(); - if (i > 0) width += GAP_BETWEEN_ICONS; - } - if (myIconsAreaWidth < width) { - myIconsAreaWidth = width + 1; - } - return true; + processGutterRenderers((line, renderers) -> { + int width = 1; + for (int i = 0; i < renderers.size(); i++) { + GutterMark renderer = renderers.get(i); + if (!checkDumbAware(renderer)) continue; + width += scaleIcon(renderer.getIcon()).getIconWidth(); + if (i > 0) width += GAP_BETWEEN_ICONS; } + if (myIconsAreaWidth < width) { + myIconsAreaWidth = width + 1; + } + return true; }); if (isDumbMode()) { @@ -817,6 +813,15 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } + @Nullable + private List getGutterRenderers(int line) { + return myLineToGutterRenderers.get(line); + } + + private void processGutterRenderers(@NotNull TIntObjectProcedure> processor) { + myLineToGutterRenderers.forEachEntry(processor); + } + private boolean isHighlighterVisible(RangeHighlighter highlighter) { int startOffset = highlighter instanceof RangeHighlighterEx ? ((RangeHighlighterEx)highlighter).getAffectedAreaStartOffset() : @@ -850,7 +855,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private void paintIcons(final int firstVisibleLine, final int lastVisibleLine, final Graphics2D g) { for (int line = firstVisibleLine; line <= lastVisibleLine; line++) { - List renderers = myLineToGutterRenderers.get(line); + List renderers = getGutterRenderers(line); if (renderers != null) { paintIconRow(line, renderers, g); } @@ -1442,7 +1447,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse if (toolTip != null && !toolTip.isEmpty()) { final Ref t = new Ref<>(e.getPoint()); int line = EditorUtil.yPositionToLogicalLine(myEditor, e); - List row = myLineToGutterRenderers.get(line); + List row = getGutterRenderers(line); Balloon.Position ballPosition = Balloon.Position.atRight; if (row != null) { final TreeMap xPos = new TreeMap<>(); @@ -1697,22 +1702,17 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse @Nullable public Point getCenterPoint(final GutterIconRenderer renderer) { final Ref result = Ref.create(); - for (int line : myLineToGutterRenderers.keys()) { - processIconsRow(line, myLineToGutterRenderers.get(line), new LineGutterIconRendererProcessor() { - @Override - public void process(int x, int y, GutterMark r) { - if (result.isNull() && r.equals(renderer)) { - Icon icon = scaleIcon(r.getIcon()); - result.set(new Point(x + icon.getIconWidth() / 2, y + icon.getIconHeight() / 2)); - } + processGutterRenderers((line, renderers) -> { + processIconsRow(line, renderers, (x, y, r) -> { + if (result.isNull() && r.equals(renderer)) { + Icon icon = scaleIcon(r.getIcon()); + result.set(new Point(x + icon.getIconWidth() / 2, y + icon.getIconHeight() / 2)); } }, true); - if (!result.isNull()) { - return result.get(); - } - } - return null; + return result.isNull(); + }); + return result.get(); } @Override @@ -1840,7 +1840,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private GutterMark getGutterRenderer(final Point p) { int line = convertPointToLineNumber(p); if (line == -1) return null; - List renderers = myLineToGutterRenderers.get(line); + List renderers = getGutterRenderers(line); if (renderers == null) { return null; } From 0d6c0670c6fd27c70603c388ee56f30750f8e4a9 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Thu, 14 Apr 2016 20:30:33 +0300 Subject: [PATCH 2/9] IDEA-154727 editor: do not synchroniously update gutter size from DocumentListener * recalculate myLineToGutterRenderers on demand (we won't just schedule updateSize() here, because this will lead to brief desync between icons and text) * do not update gutter size synchroniously in `validateSize()` --- .../impl/EditorGutterComponentImpl.java | 42 +++++++++++++------ .../openapi/editor/impl/EditorImpl.java | 6 +-- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index fa805afb9406..38dfa6eca8da 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -128,7 +128,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private final EditorImpl myEditor; private final FoldingAnchorsOverlayStrategy myAnchorsDisplayStrategy; - private TIntObjectHashMap> myLineToGutterRenderers; + @Nullable private TIntObjectHashMap> myLineToGutterRenderers; private int myIconsAreaWidth = 0; private int myLineNumberAreaWidth = 0; private int myAdditionalLineNumberAreaWidth = 0; @@ -684,6 +684,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse int prevHash = sizeHash(); if (!onLayout) { + clearLineToGutterRenderersCache(); calcLineNumberAreaWidth(); calcLineMarkerAreaWidth(canShrink); calcAnnotationsSize(); @@ -749,21 +750,15 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - private void calcLineMarkerAreaWidth(boolean canShrink) { - myLineToGutterRenderers = new TIntObjectHashMap<>(); - myLeftFreePaintersAreaShown = myForceLeftFreePaintersAreaShown; - myRightFreePaintersAreaShown = myForceRightFreePaintersAreaShown; + public void clearLineToGutterRenderersCache() { + myLineToGutterRenderers = null; + } + private void buildGutterRenderersCache() { + myLineToGutterRenderers = new TIntObjectHashMap<>(); processRangeHighlighters(0, myEditor.getDocument().getTextLength(), new RangeHighlighterProcessor() { @Override public void process(@NotNull RangeHighlighter highlighter) { - LineMarkerRenderer lineMarkerRenderer = highlighter.getLineMarkerRenderer(); - if (lineMarkerRenderer != null) { - LineMarkerRendererEx.Position position = getLineMarkerPosition(lineMarkerRenderer); - if (position == LineMarkerRendererEx.Position.LEFT && isLineMarkerVisible(highlighter)) myLeftFreePaintersAreaShown = true; - if (position == LineMarkerRendererEx.Position.RIGHT && isLineMarkerVisible(highlighter)) myRightFreePaintersAreaShown = true; - } - GutterMark renderer = highlighter.getGutterIconRenderer(); if (renderer == null) { return; @@ -784,6 +779,23 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } }); + } + + private void calcLineMarkerAreaWidth(boolean canShrink) { + myLeftFreePaintersAreaShown = myForceLeftFreePaintersAreaShown; + myRightFreePaintersAreaShown = myForceRightFreePaintersAreaShown; + + processRangeHighlighters(0, myEditor.getDocument().getTextLength(), new RangeHighlighterProcessor() { + @Override + public void process(@NotNull RangeHighlighter highlighter) { + LineMarkerRenderer lineMarkerRenderer = highlighter.getLineMarkerRenderer(); + if (lineMarkerRenderer != null) { + LineMarkerRendererEx.Position position = getLineMarkerPosition(lineMarkerRenderer); + if (position == LineMarkerRendererEx.Position.LEFT && isLineMarkerVisible(highlighter)) myLeftFreePaintersAreaShown = true; + if (position == LineMarkerRendererEx.Position.RIGHT && isLineMarkerVisible(highlighter)) myRightFreePaintersAreaShown = true; + } + } + }); if (canShrink) { myIconsAreaWidth = myEditor.getLineHeight(); @@ -815,10 +827,16 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse @Nullable private List getGutterRenderers(int line) { + if (myLineToGutterRenderers == null) { + buildGutterRenderersCache(); + } return myLineToGutterRenderers.get(line); } private void processGutterRenderers(@NotNull TIntObjectProcedure> processor) { + if (myLineToGutterRenderers == null) { + buildGutterRenderersCache(); + } myLineToGutterRenderers.forEachEntry(processor); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 1c611d0ac866..e4b0afb25ea7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -1949,8 +1949,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (myDocument.getTextLength() > 0) { int startDocLine = myDocument.getLineNumber(e.getOffset()); int endDocLine = myDocument.getLineNumber(e.getOffset() + e.getNewLength()); - if (e.getOldLength() > e.getNewLength() || startDocLine != endDocLine || StringUtil.indexOf(e.getOldFragment(), '\n') != -1) { - updateGutterSize(); + if (startDocLine != endDocLine || StringUtil.indexOf(e.getOldFragment(), '\n') != -1) { + myGutterComponent.clearLineToGutterRenderersCache(); } if (countLineFeeds(e.getOldFragment()) != countLineFeeds(e.getNewFragment())) { @@ -2036,7 +2036,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi dim = mySizeAdjustmentStrategy.adjust(dim, myPreferredSize, this); myPreferredSize = dim; - myGutterComponent.updateSize(); + updateGutterSize(); myEditorComponent.setSize(dim); myEditorComponent.fireResized(); From 1bf3de4f23c284ec692581791d66aaa897d634e1 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 19 Apr 2016 17:38:33 +0300 Subject: [PATCH 3/9] editor: remove duplication --- .../src/com/intellij/openapi/editor/impl/EditorImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index e4b0afb25ea7..1c41c4cf2770 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -1947,9 +1947,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi boolean painted = false; if (myDocument.getTextLength() > 0) { - int startDocLine = myDocument.getLineNumber(e.getOffset()); - int endDocLine = myDocument.getLineNumber(e.getOffset() + e.getNewLength()); - if (startDocLine != endDocLine || StringUtil.indexOf(e.getOldFragment(), '\n') != -1) { + if (startLine != endLine || StringUtil.indexOf(e.getOldFragment(), '\n') != -1) { myGutterComponent.clearLineToGutterRenderersCache(); } From 3bc7d8ef5d57679c3400ae58b32e370e6f3650c6 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 19 Apr 2016 15:44:01 +0300 Subject: [PATCH 4/9] vcs: show actual file names in diff title from file history * if the file was renamed, we want to show its name in requested revisions, not the current one --- .../openapi/vcs/history/VcsHistoryUtil.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java index 0df772a82089..3fc61807a3a6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java @@ -88,7 +88,16 @@ public class VcsHistoryUtil { final byte[] content1 = loadRevisionContent(revision1); final byte[] content2 = loadRevisionContent(revision2); - String title = DiffRequestFactoryImpl.getContentTitle(path); + FilePath path1 = getRevisionPath(revision1); + FilePath path2 = getRevisionPath(revision2); + + String title; + if (path1 != null && path2 != null) { + title = DiffRequestFactoryImpl.getTitle(path1, path2, " -> "); + } + else { + title = DiffRequestFactoryImpl.getContentTitle(path); + } DiffContent diffContent1 = createContent(project, content1, revision1, path); DiffContent diffContent2 = createContent(project, content2, revision2, path); @@ -113,6 +122,14 @@ public class VcsHistoryUtil { return null; } + @Nullable + private static FilePath getRevisionPath(@NotNull VcsFileRevision revision) { + if (revision instanceof VcsFileRevisionEx) { + return ((VcsFileRevisionEx)revision).getPath(); + } + return null; + } + @NotNull public static byte[] loadRevisionContent(@NotNull VcsFileRevision revision) throws VcsException, IOException { byte[] content = revision.getContent(); From 9abc16d786aa4abcc3d6e0b85f85153e3f643319 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 19 Apr 2016 17:08:20 +0200 Subject: [PATCH 5/9] let dfa inspection be found in the settings with "may produce NPE" query (IDEA-154957) --- resources-en/src/inspectionDescriptions/ConstantConditions.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources-en/src/inspectionDescriptions/ConstantConditions.html b/resources-en/src/inspectionDescriptions/ConstantConditions.html index 1e2dd7644de7..1a0040fe202e 100644 --- a/resources-en/src/inspectionDescriptions/ConstantConditions.html +++ b/resources-en/src/inspectionDescriptions/ConstantConditions.html @@ -4,7 +4,7 @@ This inspection analyzes method control and data flow to report possible conditi expressions whose value is statically proven to be constant, and situations that can lead to nullability contract violations.

Variables, method parameters and return values marked as @Nullable or @NotNull are treated as nullable (or not-null, respectively) -and used during the analysis to check nullability contracts, e.g. report possible NullPointerException errors.

+and used during the analysis to check nullability contracts, e.g. report NullPointerException (NPE) errors that might be produced.

More complex contracts can be defined using @Contract annotation, for example:

@Contract("_, null -> null") — method returns null if its second argument is null
From 77b30390335e409e5345b7b2a07dc225a115d8ad Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 19 Apr 2016 17:10:36 +0200 Subject: [PATCH 6/9] don't pollute logs with expected modal indexing start traces --- .../src/com/intellij/openapi/project/DumbServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index 39ae76b84947..1c050c8112b6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -209,7 +209,7 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica LOG.info("Dumb mode not permitted in modal environment; see DumbService.allowStartingDumbModeInside documentation", trace); } else if (permission == DumbModePermission.MAY_START_MODAL) { - LOG.info("Starting modal dumb mode, caused by the following trace", trace); + LOG.debug("Starting modal dumb mode, caused by the following trace", trace); } // always change dumb status inside write action. From 38a272870015245b16c36c3f3f2445358ac8f117 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 19 Apr 2016 17:44:39 +0200 Subject: [PATCH 7/9] fix dfa tests (IDEA-152224, IDEA-CR-10202) --- .../daemon/impl/quickfix/SimplifyBooleanExpressionFix.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java index 8d8971214f75..96d90b24c256 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java @@ -139,7 +139,7 @@ public class SimplifyBooleanExpressionFix extends LocalQuickFixOnPsiElement { PsiElement parent = orig.getParent(); if (parent == null) return; if (statement instanceof PsiBlockStatement && parent instanceof PsiCodeBlock && - !VariableSearchUtils.containsConflictingDeclarations((PsiCodeBlock)parent, (PsiCodeBlock)parent)) { + !VariableSearchUtils.containsConflictingDeclarations(((PsiBlockStatement)statement).getCodeBlock(), (PsiCodeBlock)parent)) { // See IDEADEV-24277 // Code block can only be inlined into another (parent) code block. // Code blocks, which are if or loop statement branches should not be inlined. From 1fa305d411784146efead09ceee8c31938d0de86 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 19 Apr 2016 14:10:43 +0200 Subject: [PATCH 8/9] IG: remove superfluous quotes --- .../src/com/siyeh/InspectionGadgetsBundle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index 3cb40faa79c7..d14b775a6227 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1287,7 +1287,7 @@ string.equals.empty.string.quickfix=Replace with 'length()==0' string.equals.empty.string.isempty.quickfix=Replace with 'isEmpty()' tail.recursion.replace.quickfix=Replace tail recursion with iteration if.statement.with.too.many.branches.max.option=Maximum number of branches: -if.statement.with.too.many.branches.problem.descriptor=''#ref'' has too many branches ({0}) #loc +if.statement.with.too.many.branches.problem.descriptor=#ref has too many branches ({0}) #loc negated.conditional.ignore.option=Ignore '!= null' comparisons negated.conditional.invert.quickfix=Invert condition negated.if.else.ignore.negated.null.option=Ignore '!= null' comparisons @@ -1298,9 +1298,9 @@ pointless.boolean.expression.ignore.option=Ignore named constants in determining simplifiable.conditional.expression.problem.descriptor=#ref can be simplified to ''{0}'' #loc simplifiable.if.statement.problem.descriptor=#ref statement can be replaced with ''{0}'' #loc switch.statement.density.min.option=Minimum density of branches: % -switch.statement.density.problem.descriptor=''#ref'' has too low of a branch density ({0}%) #loc +switch.statement.density.problem.descriptor=#ref has too low of a branch density ({0}%) #loc switch.statement.with.too.few.branches.min.option=Minimum number of branches: -switch.statement.with.too.few.branches.problem.descriptor=''#ref'' has too few branches ({0}), and should probably be replaced with an ''if'' statement #loc +switch.statement.with.too.few.branches.problem.descriptor=#ref has too few branches ({0}), and should probably be replaced with an ''if'' statement #loc switch.statement.without.default.ignore.option=Ignore if all cases of an enumerated type are covered unnecessary.label.remove.quickfix=Remove label unnecessary.return.problem.descriptor=#ref is unnecessary as the last statement in a 'void' method #loc From 7b20431b23155f6dd4372ea3cd8ef1fc3159bb08 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 19 Apr 2016 16:55:58 +0200 Subject: [PATCH 9/9] IDEA-154929 (Create missing 'switch' branches breaks logic) --- .../CreateEnumSwitchBranchesIntention.java | 14 ++++++++++++-- .../EnumSwitchBranchesIntentionTest.java | 3 ++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/enumswitch/CreateEnumSwitchBranchesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/enumswitch/CreateEnumSwitchBranchesIntention.java index 9f2078cac24f..fac06bb8dc6a 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/enumswitch/CreateEnumSwitchBranchesIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/enumswitch/CreateEnumSwitchBranchesIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2016 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. @@ -16,6 +16,7 @@ package com.siyeh.ipp.enumswitch; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.siyeh.ig.PsiReplacementUtil; import com.siyeh.ipp.base.Intention; import com.siyeh.ipp.base.PsiElementPredicate; @@ -29,11 +30,13 @@ import java.util.Map; public class CreateEnumSwitchBranchesIntention extends Intention { + @Override @NotNull protected PsiElementPredicate getElementPredicate() { return new EnumSwitchPredicate(); } + @Override public void processIntention(@NotNull PsiElement element) { if (element instanceof PsiWhiteSpace) { element = element.getPrevSibling(); @@ -54,7 +57,7 @@ public class CreateEnumSwitchBranchesIntention extends Intention { return; } final PsiField[] fields = enumClass.getFields(); - final List missingEnumElements = new ArrayList(fields.length); + final List missingEnumElements = new ArrayList<>(fields.length); for (final PsiField field : fields) { if (!(field instanceof PsiEnumConstant)) { continue; @@ -114,6 +117,13 @@ public class CreateEnumSwitchBranchesIntention extends Intention { } private static void addSwitchLabelStatementBefore(PsiEnumConstant missingEnumElement, PsiElement anchor) { + if (anchor instanceof PsiSwitchLabelStatement) { + PsiElement sibling = PsiTreeUtil.skipSiblingsBackward(anchor, PsiWhiteSpace.class); + while (sibling instanceof PsiSwitchLabelStatement) { + anchor = sibling; + sibling = PsiTreeUtil.skipSiblingsBackward(anchor, PsiWhiteSpace.class); + } + } final PsiElement parent = anchor.getParent(); final PsiElementFactory factory = JavaPsiFacade.getElementFactory(anchor.getProject()); final PsiStatement caseStatement = factory.createStatementFromText("case " + missingEnumElement.getName() + ":", anchor); diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/enumswitch/EnumSwitchBranchesIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/enumswitch/EnumSwitchBranchesIntentionTest.java index 0cee31ba1abd..9a7d0f79688b 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/enumswitch/EnumSwitchBranchesIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/enumswitch/EnumSwitchBranchesIntentionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -25,6 +25,7 @@ public class EnumSwitchBranchesIntentionTest extends IPPTestCase { public void testWithoutBraces() { doTest(); } public void testBeforeDefault() { doTest(); } + public void testBeforeFallthrough() { doTest(); } public void testMultiple() { doTest(); } public void testNoActionAfterBraces() { assertIntentionNotAvailable(); }