From 6cf80674b1f2f03204fdf641fa5dcf76e5e81b1e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 23 Jun 2016 14:27:43 +0300 Subject: [PATCH 01/36] cleanup --- .../src/com/intellij/util/concurrency/SchedulingWrapper.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/concurrency/SchedulingWrapper.java b/platform/util/src/com/intellij/util/concurrency/SchedulingWrapper.java index 52aad13bc246..bdf89a41ddd6 100644 --- a/platform/util/src/com/intellij/util/concurrency/SchedulingWrapper.java +++ b/platform/util/src/com/intellij/util/concurrency/SchedulingWrapper.java @@ -183,8 +183,7 @@ class SchedulingWrapper implements ScheduledExecutorService { @Override public int compareTo(@NotNull Delayed other) { - if (other == this) // compare zero if same object - { + if (other == this) { return 0; } if (other instanceof MyScheduledFutureTask) { From 73684fa942160fb21071923ef04df52d9bb0f234 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 24 Jun 2016 12:04:16 +0300 Subject: [PATCH 02/36] more diagnostics on exception in applyInformation --- .../daemon/impl/PassExecutorService.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java index 534ec24f9e19..87c490400fec 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java @@ -35,18 +35,17 @@ import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.TextEditor; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import gnu.trove.THashMap; @@ -57,7 +56,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; import java.util.*; -import java.util.concurrent.*; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -506,10 +508,18 @@ class PassExecutorService implements Disposable { pass.applyInformationToEditor(); } } - catch (RuntimeException e) { + catch (ProcessCanceledException e) { log(updateProgress, pass, "Error " + e); throw e; } + catch (RuntimeException e) { + Document document = pass.getDocument(); + VirtualFile file = document == null ? null : FileDocumentManager.getInstance().getFile(document); + FileType fileType = file == null ? null : file.getFileType(); + String message = "Exception while applying information to " + fileEditor + "("+fileType+")"; + log(updateProgress, pass, message + e); + throw new RuntimeException(message, e); + } if (threadsToStartCountdown.decrementAndGet() == 0) { log(updateProgress, pass, "Stopping "); updateProgress.stopIfRunning(); From 1699a0d80ded08a38e5c87b28ad9be6737395582 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 24 Jun 2016 12:05:59 +0300 Subject: [PATCH 03/36] notnull, cleanup --- .../fileEditor/TextEditorLocation.java | 2 +- .../com/intellij/openapi/wm/ToolWindow.java | 6 +- .../intellij/openapi/wm/ToolWindowAnchor.java | 13 +- .../openapi/wm/ToolWindowManager.java | 24 +- .../intellij/designer/LightToolWindow.java | 25 +- .../DefaultFrameEditorComponentProvider.java | 5 +- .../wm/ex/FrameEditorComponentProvider.java | 4 +- .../openapi/wm/ex/ToolWindowManagerEx.java | 7 +- .../intellij/openapi/wm/impl/ActiveStack.java | 20 +- .../openapi/wm/impl/DesktopLayout.java | 66 ++-- .../openapi/wm/impl/FloatingDecorator.java | 5 +- .../openapi/wm/impl/InternalDecorator.java | 12 +- .../wm/impl/InternalDecoratorListener.java | 20 +- .../com/intellij/openapi/wm/impl/Stripe.java | 7 +- .../openapi/wm/impl/ToolWindowHeader.java | 53 +-- .../impl/ToolWindowHeadlessManagerImpl.java | 34 +- .../openapi/wm/impl/ToolWindowImpl.java | 34 +- .../wm/impl/ToolWindowManagerImpl.java | 372 +++++++----------- .../openapi/wm/impl/ToolWindowsPane.java | 236 +++++------ .../openapi/wm/impl/WindowInfoImpl.java | 80 ++-- .../openapi/wm/impl/WindowedDecorator.java | 5 +- .../wm/impl/commands/FinalizableCommand.java | 7 +- .../src/com/intellij/mock/Mock.java | 8 +- .../src/com/intellij/util/RetinaImage.java | 4 + .../util/src/com/intellij/util/ui/UIUtil.java | 2 + 25 files changed, 513 insertions(+), 538 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/TextEditorLocation.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/TextEditorLocation.java index 9477beb04a11..ef1c4ed6dd23 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/TextEditorLocation.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/TextEditorLocation.java @@ -50,7 +50,7 @@ public class TextEditorLocation implements FileEditorLocation { } @Override - public int compareTo(FileEditorLocation fileEditorLocation) { + public int compareTo(@NotNull FileEditorLocation fileEditorLocation) { TextEditorLocation otherLocation = (TextEditorLocation)fileEditorLocation; if (myEditor != otherLocation.myEditor) { LOG.error("Different editors: " + myEditor + "; and " + otherLocation.myEditor); diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java index 841b46bf6148..9460fd2c3f36 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java @@ -29,7 +29,7 @@ import java.awt.event.InputEvent; public interface ToolWindow extends BusyObject { - Key SHOW_CONTENT_ICON = new Key("ContentIcon"); + Key SHOW_CONTENT_ICON = new Key<>("ContentIcon"); /** * @exception IllegalStateException if tool window isn't installed. @@ -74,7 +74,7 @@ public interface ToolWindow extends BusyObject { /** * @exception IllegalStateException if tool window isn't installed. */ - void setAnchor(ToolWindowAnchor anchor, @Nullable Runnable runnable); + void setAnchor(@NotNull ToolWindowAnchor anchor, @Nullable Runnable runnable); /** * @exception IllegalStateException if tool window isn't installed. @@ -104,7 +104,7 @@ public interface ToolWindow extends BusyObject { /** * @exception IllegalStateException if tool window isn't installed. */ - void setType(ToolWindowType type, @Nullable Runnable runnable); + void setType(@NotNull ToolWindowType type, @Nullable Runnable runnable); /** * @return window icon. Returns null if window has no icon. diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowAnchor.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowAnchor.java index 1628a6f679bf..88f544d237de 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowAnchor.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowAnchor.java @@ -17,6 +17,7 @@ package com.intellij.openapi.wm; import com.intellij.ide.ui.UISettings; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -26,9 +27,10 @@ public final class ToolWindowAnchor { public static final ToolWindowAnchor BOTTOM = new ToolWindowAnchor("bottom"); public static final ToolWindowAnchor RIGHT = new ToolWindowAnchor("right"); + @NotNull private final String myText; - private ToolWindowAnchor(@NonNls String text){ + private ToolWindowAnchor(@NonNls @NotNull String text){ myText = text; } @@ -40,6 +42,7 @@ public final class ToolWindowAnchor { return this == TOP || this == BOTTOM; } + @NotNull public static ToolWindowAnchor get(int swingOrientationConstant) { switch(swingOrientationConstant) { case SwingConstants.TOP: @@ -56,12 +59,16 @@ public final class ToolWindowAnchor { } public boolean isSplitVertically() { - return (this == LEFT && !UISettings.getInstance().LEFT_HORIZONTAL_SPLIT) || (this == RIGHT && !UISettings.getInstance().RIGHT_HORIZONTAL_SPLIT); + return this == LEFT && !UISettings.getInstance().LEFT_HORIZONTAL_SPLIT + || this == RIGHT && !UISettings.getInstance().RIGHT_HORIZONTAL_SPLIT; } + @NotNull public static ToolWindowAnchor fromText(String anchor) { for (ToolWindowAnchor a : new ToolWindowAnchor[]{TOP, LEFT, BOTTOM, RIGHT}) { - if (a.myText.equals(anchor)) return a; + if (a.myText.equals(anchor)) { + return a; + } } throw new IllegalArgumentException("Unknown anchor constant: " + anchor); } diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java index 8baa090b2af2..96fbb41189ad 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java @@ -73,7 +73,7 @@ public abstract class ToolWindowManager { public abstract ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode); /** * @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} @@ -83,7 +83,7 @@ public abstract class ToolWindowManager { public abstract ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean canCloseContents); @@ -91,19 +91,31 @@ public abstract class ToolWindowManager { public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor); @NotNull - public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, boolean secondary); + public abstract ToolWindow registerToolWindow(@NotNull String id, + boolean canCloseContent, + @NotNull ToolWindowAnchor anchor, + boolean secondary); @NotNull - public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable, boolean canWorkInDumbMode); + public abstract ToolWindow registerToolWindow(@NotNull String id, + boolean canCloseContent, + @NotNull ToolWindowAnchor anchor, + @NotNull Disposable parentDisposable, + boolean canWorkInDumbMode); @NotNull - public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable, boolean canWorkInDumbMode, boolean secondary); + public abstract ToolWindow registerToolWindow(@NotNull String id, + boolean canCloseContent, + @NotNull ToolWindowAnchor anchor, + @NotNull Disposable parentDisposable, + boolean canWorkInDumbMode, + boolean secondary); @NotNull public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, - final Disposable parentDisposable) { + @NotNull Disposable parentDisposable) { return registerToolWindow(id, canCloseContent, anchor, parentDisposable, false); } diff --git a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java index 7bdb59ea19e2..b1b8a84de370 100644 --- a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java +++ b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java @@ -46,9 +46,9 @@ import java.awt.event.*; * @author Alexander Lobas */ public class LightToolWindow extends JPanel { - public static final String LEFT_MIN_KEY = "left"; - public static final String RIGHT_MIN_KEY = "right"; - public static final int MINIMIZE_WIDTH = 25; + static final String LEFT_MIN_KEY = "left"; + static final String RIGHT_MIN_KEY = "right"; + static final int MINIMIZE_WIDTH = 25; private static final String IGNORE_WIDTH_KEY = "ignore_width"; private final LightToolWindowContent myContent; @@ -139,12 +139,14 @@ public class LightToolWindow extends JPanel { add(contentWrapper, BorderLayout.CENTER); addMouseListener(new MouseAdapter() { + @Override public void mouseReleased(final MouseEvent e) { IdeFocusManager.getInstance(myProject).requestFocus(myFocusedComponent, true); } }); addMouseListener(new PopupHandler() { + @Override public void invokePopup(Component component, int x, int y) { showGearPopup(component, x, y); } @@ -167,12 +169,9 @@ public class LightToolWindow extends JPanel { return myAnchor; } }; - myMinimizeButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - myMinimizeButton.setSelected(false); - updateContent(true, true); - } + myMinimizeButton.addActionListener(e -> { + myMinimizeButton.setSelected(false); + updateContent(true, true); }); myMinimizeButton.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5)); myMinimizeButton.setFocusable(false); @@ -233,7 +232,7 @@ public class LightToolWindow extends JPanel { } } - public void updateAnchor(ToolWindowAnchor newAnchor) { + void updateAnchor(ToolWindowAnchor newAnchor) { JComponent minimizeParent = myContentSplitter.getInnerComponent(); minimizeParent.putClientProperty(IGNORE_WIDTH_KEY, Boolean.TRUE); @@ -374,7 +373,7 @@ public class LightToolWindow extends JPanel { } private class GearAction extends AnAction { - public GearAction() { + GearAction() { Presentation presentation = getTemplatePresentation(); presentation.setIcon(AllIcons.General.Gear); presentation.setHoveredIcon(AllIcons.General.GearHover); @@ -462,7 +461,7 @@ public class LightToolWindow extends JPanel { } private class ToggleWindowedModeAction extends ToggleTypeModeAction { - public ToggleWindowedModeAction() { + ToggleWindowedModeAction() { super(ToolWindowType.WINDOWED, InternalDecorator.TOGGLE_WINDOWED_MODE_ACTION_ID); } @@ -475,7 +474,7 @@ public class LightToolWindow extends JPanel { private class ToggleTypeModeAction extends ToggleAction { private final ToolWindowType myType; - public ToggleTypeModeAction(ToolWindowType type, String id) { + ToggleTypeModeAction(@NotNull ToolWindowType type, @NotNull String id) { myType = type; copyFrom(ActionManager.getInstance().getAction(id)); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/DefaultFrameEditorComponentProvider.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/DefaultFrameEditorComponentProvider.java index efab9e503b62..96346063e4a4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/DefaultFrameEditorComponentProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/DefaultFrameEditorComponentProvider.java @@ -2,6 +2,7 @@ package com.intellij.openapi.wm.ex; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -10,8 +11,8 @@ import javax.swing.*; */ public class DefaultFrameEditorComponentProvider implements FrameEditorComponentProvider { @Override - public JComponent createEditorComponent(Project project) { + public JComponent createEditorComponent(@NotNull Project project) { FileEditorManagerEx editorManager = FileEditorManagerEx.getInstanceEx(project); - return editorManager.getComponent(); + return editorManager.getComponent(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/FrameEditorComponentProvider.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/FrameEditorComponentProvider.java index f6fce90c56ab..5f012185e89e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/FrameEditorComponentProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/FrameEditorComponentProvider.java @@ -2,14 +2,16 @@ package com.intellij.openapi.wm.ex; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; import javax.swing.*; /** * @author Konstantin Bulenkov */ +@FunctionalInterface public interface FrameEditorComponentProvider { ExtensionPointName EP = ExtensionPointName.create("com.intellij.frameEditorComponentProvider"); - JComponent createEditorComponent(Project project); + JComponent createEditorComponent(@NotNull Project project); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java index d8414ddc37ed..f38d3bab16b2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java @@ -35,9 +35,9 @@ public abstract class ToolWindowManagerEx extends ToolWindowManager { return (ToolWindowManagerEx)getInstance(project); } - public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l); - public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable); - public abstract void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l); + public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener); + public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener, @NotNull Disposable parentDisposable); + public abstract void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener listener); /** * @return ID of tool window that was activated last time. @@ -69,5 +69,6 @@ public abstract class ToolWindowManagerEx extends ToolWindowManager { public abstract void hideToolWindow(@NotNull String id, boolean hideSide); + @NotNull public abstract List getIdsOn(@NotNull ToolWindowAnchor anchor); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActiveStack.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActiveStack.java index ef8cdf338406..f99d3e221238 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActiveStack.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActiveStack.java @@ -15,8 +15,10 @@ */ package com.intellij.openapi.wm.impl; +import com.intellij.util.containers.Stack; +import org.jetbrains.annotations.NotNull; + import java.util.Iterator; -import java.util.Stack; /** * Actually this class represent two stacks. @@ -43,8 +45,8 @@ final class ActiveStack { * Creates enabled window stack. */ ActiveStack() { - myStack = new Stack(); - myPersistentStack = new Stack(); + myStack = new Stack<>(); + myPersistentStack = new Stack<>(); } /** @@ -61,10 +63,12 @@ final class ActiveStack { return myStack.isEmpty(); } + @NotNull String pop() { return myStack.pop(); } + @NotNull String peek() { return myStack.peek(); } @@ -73,10 +77,12 @@ final class ActiveStack { return myStack.size(); } - String peek(int i) { + @NotNull + private String peek(int i) { return myStack.get(getSize() - i - 1); } + @NotNull String[] getStack() { String[] result = new String[getSize()]; for (int i = 0; i < getSize(); i++) { @@ -85,6 +91,7 @@ final class ActiveStack { return result; } + @NotNull String[] getPersistentStack() { String[] result = new String[getPersistentSize()]; for (int i = 0; i < getPersistentSize(); i++) { @@ -93,7 +100,7 @@ final class ActiveStack { return result; } - void push(final String id) { + void push(@NotNull String id) { remove(id, true); myStack.push(id); myPersistentStack.push(id); @@ -106,6 +113,7 @@ final class ActiveStack { /** * Peeks element at the persistent stack. 0 means the top of the stack. */ + @NotNull String peekPersistent(final int index) { return myPersistentStack.get(myPersistentStack.size() - index - 1); } @@ -117,7 +125,7 @@ final class ActiveStack { * @param removePersistentAlso if true then clears last active ID * if it's the last active ID. */ - void remove(final String id, final boolean removePersistentAlso) { + void remove(@NotNull String id, final boolean removePersistentAlso) { for (Iterator i = myStack.iterator(); i.hasNext();) { if (id.equals(i.next())) { i.remove(); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java index 62c77fcb1357..a3cc0dea6e31 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java @@ -36,11 +36,11 @@ public final class DesktopLayout implements JDOMExternalizable { /** * Map between ids and registered WindowInfos. */ - private final Map myRegisteredId2Info; + private final Map myRegisteredId2Info = new HashMap<>(); /** * Map between ids and unregistered WindowInfos. */ - private final Map myUnregisteredId2Info; + private final Map myUnregisteredId2Info = new HashMap<>(); /** * */ @@ -63,19 +63,15 @@ public final class DesktopLayout implements JDOMExternalizable { * if the cached data is invalid. */ private WindowInfoImpl[] myAllInfos; - @NonNls public static final String ID_ATTR = "id"; + @NonNls private static final String ID_ATTR = "id"; - public DesktopLayout() { - myRegisteredId2Info = new HashMap(); - myUnregisteredId2Info = new HashMap(); - } /** * Copies itself from the passed * * @param layout to be copied. */ - public final void copyFrom(final DesktopLayout layout) { + public final void copyFrom(@NotNull DesktopLayout layout) { final WindowInfoImpl[] infos = layout.getAllInfos(); for (WindowInfoImpl info1 : infos) { WindowInfoImpl info = myRegisteredId2Info.get(info1.getId()); @@ -128,7 +124,7 @@ public final class DesktopLayout implements JDOMExternalizable { return info; } - final void unregister(final String id) { + final void unregister(@NotNull String id) { final WindowInfoImpl info = myRegisteredId2Info.remove(id).copy(); myUnregisteredId2Info.put(id, info); // invalidate caches @@ -142,14 +138,12 @@ public final class DesktopLayout implements JDOMExternalizable { * If onlyRegistered is true then returns not null * value if and only if window with id is registered one. */ - final WindowInfoImpl getInfo(final String id, final boolean onlyRegistered) { + final WindowInfoImpl getInfo(String id, final boolean onlyRegistered) { final WindowInfoImpl info = myRegisteredId2Info.get(id); if (onlyRegistered || info != null) { return info; } - else { - return myUnregisteredId2Info.get(id); - } + return myUnregisteredId2Info.get(id); } @Nullable @@ -166,6 +160,7 @@ public final class DesktopLayout implements JDOMExternalizable { /** * @return WindowInfos for all registered tool windows. */ + @NotNull final WindowInfoImpl[] getInfos() { if (myRegisteredInfos == null) { myRegisteredInfos = myRegisteredId2Info.values().toArray(new WindowInfoImpl[myRegisteredId2Info.size()]); @@ -176,6 +171,7 @@ public final class DesktopLayout implements JDOMExternalizable { /** * @return WindowInfoss for all windows that are currently unregistered. */ + @NotNull private WindowInfoImpl[] getUnregisteredInfos() { if (myUnregisteredInfos == null) { myUnregisteredInfos = myUnregisteredId2Info.values().toArray(new WindowInfoImpl[myUnregisteredId2Info.size()]); @@ -186,7 +182,8 @@ public final class DesktopLayout implements JDOMExternalizable { /** * @return WindowInfos of all (registered and unregistered) tool windows. */ - WindowInfoImpl[] getAllInfos() { + @NotNull + private WindowInfoImpl[] getAllInfos() { final WindowInfoImpl[] registeredInfos = getInfos(); final WindowInfoImpl[] unregisteredInfos = getUnregisteredInfos(); myAllInfos = ArrayUtil.mergeArrays(registeredInfos, unregisteredInfos); @@ -197,9 +194,10 @@ public final class DesktopLayout implements JDOMExternalizable { * @return all (registered and not unregistered) WindowInfos for the specified anchor. * Returned infos are sorted by order. */ - private WindowInfoImpl[] getAllInfos(final ToolWindowAnchor anchor) { + @NotNull + private WindowInfoImpl[] getAllInfos(@NotNull ToolWindowAnchor anchor) { WindowInfoImpl[] infos = getAllInfos(); - final ArrayList list = new ArrayList(infos.length); + final ArrayList list = new ArrayList<>(infos.length); for (WindowInfoImpl info : infos) { if (anchor == info.getAnchor()) { list.add(info); @@ -214,7 +212,7 @@ public final class DesktopLayout implements JDOMExternalizable { * Normalizes order of windows in the passed array. Note, that array should be * sorted by order (by ascending). Order of first window will be 0. */ - private static void normalizeOrder(final WindowInfoImpl[] infos) { + private static void normalizeOrder(@NotNull WindowInfoImpl[] infos) { for (int i = 0; i < infos.length; i++) { infos[i].setOrder(i); } @@ -228,7 +226,8 @@ public final class DesktopLayout implements JDOMExternalizable { * @return comparator which compares StripeButtons in the stripe with * specified anchor. */ - final Comparator comparator(final ToolWindowAnchor anchor) { + @NotNull + final Comparator comparator(@NotNull ToolWindowAnchor anchor) { return new MyStripeButtonComparator(anchor); } @@ -237,7 +236,7 @@ public final class DesktopLayout implements JDOMExternalizable { * @return maximum ordinal number in the specified stripe. Returns -1 * if there is no any tool window with the specified anchor. */ - private int getMaxOrder(final ToolWindowAnchor anchor) { + private int getMaxOrder(@NotNull ToolWindowAnchor anchor) { int res = -1; final WindowInfoImpl[] infos = getAllInfos(); for (final WindowInfoImpl info : infos) { @@ -255,7 +254,7 @@ public final class DesktopLayout implements JDOMExternalizable { * @param newAnchor new anchor * @param newOrder new order */ - final void setAnchor(final String id, final ToolWindowAnchor newAnchor, int newOrder) { + final void setAnchor(@NotNull String id, @NotNull ToolWindowAnchor newAnchor, int newOrder) { if (newOrder == -1) { // if order isn't defined then the window will the last in the stripe newOrder = getMaxOrder(newAnchor) + 1; } @@ -279,11 +278,12 @@ public final class DesktopLayout implements JDOMExternalizable { } } - final void setSplitMode(final String id, boolean split) { + final void setSplitMode(@NotNull String id, boolean split) { final WindowInfoImpl info = getInfo(id, true); info.setSplit(split); } + @Override public final void readExternal(final Element layoutElement) { myUnregisteredInfos = null; for (Object o : layoutElement.getChildren()) { @@ -301,6 +301,7 @@ public final class DesktopLayout implements JDOMExternalizable { } } + @Override public final void writeExternal(final Element layoutElement) { final WindowInfoImpl[] infos = getAllInfos(); for (WindowInfoImpl info : infos) { @@ -310,30 +311,30 @@ public final class DesktopLayout implements JDOMExternalizable { } } - public List getVisibleIdsOn(final ToolWindowAnchor anchor, ToolWindowManagerImpl manager) { - ArrayList ids = new ArrayList(); + @NotNull + List getVisibleIdsOn(@NotNull ToolWindowAnchor anchor, @NotNull ToolWindowManagerImpl manager) { + List ids = new ArrayList<>(); for (WindowInfoImpl each : getAllInfos(anchor)) { - if (manager == null) break; - final ToolWindow window = manager.getToolWindow(each.getId()); - if (window == null) continue; - if (window.isAvailable() || UISettings.getInstance().ALWAYS_SHOW_WINDOW_BUTTONS) { - ids.add(each.getId()); - } + final ToolWindow window = manager.getToolWindow(each.getId()); + if (window == null) continue; + if (window.isAvailable() || UISettings.getInstance().ALWAYS_SHOW_WINDOW_BUTTONS) { + ids.add(each.getId()); + } } return ids; } private static final class MyWindowInfoComparator implements Comparator { + @Override public int compare(final WindowInfoImpl info1, final WindowInfoImpl info2) { return info1.getOrder() - info2.getOrder(); } } private final class MyStripeButtonComparator implements Comparator { - private final HashMap myId2Info; + private final HashMap myId2Info = new HashMap<>(); - public MyStripeButtonComparator(final ToolWindowAnchor anchor) { - myId2Info = new HashMap(); + public MyStripeButtonComparator(@NotNull ToolWindowAnchor anchor) { final WindowInfoImpl[] infos = getInfos(); for (final WindowInfoImpl info : infos) { if (anchor == info.getAnchor()) { @@ -342,6 +343,7 @@ public final class DesktopLayout implements JDOMExternalizable { } } + @Override public final int compare(final StripeButton obj1, final StripeButton obj2) { final WindowInfoImpl info1 = myId2Info.get(obj1.getWindowInfo().getId()); final int order1 = info1 != null ? info1.getOrder() : 0; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java index dabd6ada57f2..c3d0bc2f54fb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java @@ -28,6 +28,7 @@ import com.intellij.ui.JBColor; import com.intellij.ui.ScreenUtil; import com.intellij.util.Alarm; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -66,7 +67,7 @@ public final class FloatingDecorator extends JDialog { private float myEndRatio; // start and end alpha ratio for transparency animation - FloatingDecorator(final IdeFrameImpl owner,final WindowInfoImpl info,final InternalDecorator internalDecorator){ + FloatingDecorator(final IdeFrameImpl owner, @NotNull WindowInfoImpl info, @NotNull InternalDecorator internalDecorator){ super(owner,internalDecorator.getToolWindow().getId()); MnemonicHelper.init(getContentPane()); myInternalDecorator=internalDecorator; @@ -154,7 +155,7 @@ public final class FloatingDecorator extends JDialog { super.dispose(); } - final void apply(final WindowInfoImpl info){ + final void apply(@NotNull WindowInfoImpl info){ LOG.assertTrue(info.isFloating()); myInfo=info; // Set alpha mode diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java index 2dcec6aed305..a214765244fa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java @@ -116,7 +116,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr } @Override - protected void toolWindowTypeChanged(ToolWindowType type) { + protected void toolWindowTypeChanged(@NotNull ToolWindowType type) { fireTypeChanged(type); } @@ -214,7 +214,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr myProject = null; } - private void fireAnchorChanged(ToolWindowAnchor anchor) { + private void fireAnchorChanged(@NotNull ToolWindowAnchor anchor) { myDispatcher.getMulticaster().anchorChanged(this, anchor); } @@ -243,7 +243,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr myDispatcher.getMulticaster().activated(this); } - private void fireTypeChanged(ToolWindowType type) { + private void fireTypeChanged(@NotNull ToolWindowType type) { myDispatcher.getMulticaster().typeChanged(this, type); } @@ -255,7 +255,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr myDispatcher.getMulticaster().sideStatusChanged(this, isSide); } - private void fireContentUiTypeChanges(ToolWindowContentUiType type) { + private void fireContentUiTypeChanges(@NotNull ToolWindowContentUiType type) { myDispatcher.getMulticaster().contentUiTypeChanges(this, type); } @@ -512,9 +512,9 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr } private final class ChangeAnchorAction extends AnAction implements DumbAware { - private final ToolWindowAnchor myAnchor; + @NotNull private final ToolWindowAnchor myAnchor; - public ChangeAnchorAction(final String title, final ToolWindowAnchor anchor) { + public ChangeAnchorAction(@NotNull String title, @NotNull ToolWindowAnchor anchor) { super(title); myAnchor = anchor; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecoratorListener.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecoratorListener.java index b59657225a06..38bba5916e71 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecoratorListener.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecoratorListener.java @@ -27,23 +27,23 @@ import java.util.EventListener; */ interface InternalDecoratorListener extends EventListener{ - public void anchorChanged(InternalDecorator source,ToolWindowAnchor anchor); + void anchorChanged(@NotNull InternalDecorator source, @NotNull ToolWindowAnchor anchor); - public void autoHideChanged(InternalDecorator source,boolean autoHide); + void autoHideChanged(@NotNull InternalDecorator source, boolean autoHide); - public void hidden(InternalDecorator source); + void hidden(@NotNull InternalDecorator source); - public void hiddenSide(InternalDecorator source); + void hiddenSide(@NotNull InternalDecorator source); - public void resized(InternalDecorator source); + void resized(@NotNull InternalDecorator source); - public void activated(InternalDecorator source); + void activated(@NotNull InternalDecorator source); - public void typeChanged(InternalDecorator source,ToolWindowType type); + void typeChanged(@NotNull InternalDecorator source, @NotNull ToolWindowType type); - public void sideStatusChanged(InternalDecorator source,boolean isSideTool); + void sideStatusChanged(@NotNull InternalDecorator source, boolean isSideTool); - public void contentUiTypeChanges(InternalDecorator sources, @NotNull ToolWindowContentUiType type); + void contentUiTypeChanges(@NotNull InternalDecorator sources, @NotNull ToolWindowContentUiType type); - public void visibleStripeButtonChanged(InternalDecorator source, boolean visible); + void visibleStripeButtonChanged(@NotNull InternalDecorator source, boolean visible); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java index 53124343ae01..a381b93e5168 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java @@ -28,6 +28,7 @@ import com.intellij.ui.ColorUtil; import com.intellij.ui.Gray; import com.intellij.ui.ScreenUtil; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -166,7 +167,7 @@ final class Stripe extends JPanel implements UISettingsListener { super.removeNotify(); } - void addButton(final StripeButton button, final Comparator comparator) { + void addButton(@NotNull StripeButton button, final Comparator comparator) { myPrefSize = null; myButtons.add(button); Collections.sort(myButtons, comparator); @@ -174,7 +175,7 @@ final class Stripe extends JPanel implements UISettingsListener { revalidate(); } - void removeButton(final StripeButton button) { + void removeButton(@NotNull StripeButton button) { myPrefSize = null; myButtons.remove(button); remove(button); @@ -475,7 +476,7 @@ final class Stripe extends JPanel implements UISettingsListener { } } - public boolean containsScreen(final Rectangle screenRec) { + public boolean containsScreen(@NotNull Rectangle screenRec) { final Point point = screenRec.getLocation(); SwingUtilities.convertPointFromScreen(point, this); return new Rectangle(point, screenRec.getSize()).intersects( diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java index 66633a9f6d83..dc3c222572be 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java @@ -49,7 +49,6 @@ import javax.swing.plaf.PanelUI; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; -import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; @@ -74,7 +73,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS private final DefaultActionGroup myActionGroup = new DefaultActionGroup(); private List myVisibleActions = ContainerUtil.newArrayListWithCapacity(2); - public ToolWindowHeader(final ToolWindowImpl toolWindow, @NotNull WindowInfoImpl info, @NotNull final Producer gearProducer) { + ToolWindowHeader(final ToolWindowImpl toolWindow, @NotNull WindowInfoImpl info, @NotNull final Producer gearProducer) { setLayout(new BorderLayout()); myToolWindow = toolWindow; @@ -89,7 +88,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS Component c = getComponent(0); Dimension size = c.getPreferredSize(); - if (size.width < (r.width - insets.left - insets.right)) { + if (size.width < r.width - insets.left - insets.right) { c.setBounds(insets.left, insets.top, size.width, r.height - insets.top - insets.bottom); } else { c.setBounds(insets.left, insets.top, r.width - insets.left - insets.right, r.height - insets.top - insets.bottom); @@ -170,6 +169,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS myButtonPanel = eastPanel; westPanel.addMouseListener(new PopupHandler() { + @Override public void invokePopup(final Component comp, final int x, final int y) { toolWindow.getContentUI().showContextMenu(comp, x, y, toolWindow.getPopupGroup(), toolWindow.getContentManager().getSelectedContent()); } @@ -182,6 +182,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS }); addMouseListener(new MouseAdapter() { + @Override public void mouseReleased(final MouseEvent e) { if (!e.isPopupTrigger()) { if (UIUtil.isCloseClick(e, MouseEvent.MOUSE_RELEASED)) { @@ -227,7 +228,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS @Override public void mouseReleased(final MouseEvent e) { Runnable runnable = - () -> ToolWindowHeader.this.dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, ToolWindowHeader.this)); + () -> dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, ToolWindowHeader.this)); //noinspection SSBasedInspection SwingUtilities.invokeLater(runnable); } @@ -253,7 +254,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS myInfo = null; } - public void setAdditionalTitleActions(AnAction[] actions) { + void setAdditionalTitleActions(AnAction[] actions) { myActionGroup.removeAll(); myActionGroup.addAll(actions); myUpdater.updateActions(false, true); @@ -300,7 +301,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS if (anchor == ToolWindowAnchor.BOTTOM) { return AllIcons.General.HideDownPart; } - else if (anchor == ToolWindowAnchor.RIGHT) { + if (anchor == ToolWindowAnchor.RIGHT) { return AllIcons.General.HideRightPart; } @@ -312,7 +313,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS if (anchor == ToolWindowAnchor.BOTTOM) { return AllIcons.General.HideDown; } - else if (anchor == ToolWindowAnchor.RIGHT) { + if (anchor == ToolWindowAnchor.RIGHT) { return AllIcons.General.HideRight; } @@ -324,7 +325,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS if (anchor == ToolWindowAnchor.BOTTOM) { return AllIcons.General.HideDownPartHover; } - else if (anchor == ToolWindowAnchor.RIGHT) { + if (anchor == ToolWindowAnchor.RIGHT) { return AllIcons.General.HideRightPartHover; } @@ -336,7 +337,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS if (anchor == ToolWindowAnchor.BOTTOM) { return AllIcons.General.HideDownHover; } - else if (anchor == ToolWindowAnchor.RIGHT) { + if (anchor == ToolWindowAnchor.RIGHT) { return AllIcons.General.HideRightHover; } @@ -419,7 +420,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS protected abstract void sideHidden(); - protected abstract void toolWindowTypeChanged(ToolWindowType type); + protected abstract void toolWindowTypeChanged(@NotNull ToolWindowType type); @Override public Dimension getPreferredSize() { @@ -468,18 +469,15 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS setIcon(getActiveIcon(), getInactiveIcon() == null ? getActiveIcon() : getInactiveIcon(), getActiveHoveredIcon()); - PropertyChangeListener listener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (myAlternativeAction == null) return; - if ("ancestor".equals(evt.getPropertyName())) { - if (evt.getNewValue() == null) { - AltStateManager.getInstance().removeListener(ActionButton.this); - switchAlternativeAction(false); - } - else { - AltStateManager.getInstance().addListener(ActionButton.this); - } + PropertyChangeListener listener = evt -> { + if (myAlternativeAction == null) return; + if ("ancestor".equals(evt.getPropertyName())) { + if (evt.getNewValue() == null) { + AltStateManager.getInstance().removeListener(this); + switchAlternativeAction(false); + } + else { + AltStateManager.getInstance().addListener(this); } } }; @@ -487,7 +485,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS addPropertyChangeListener(listener); } - public void updateTooltip() { + void updateTooltip() { myButton.setToolTipText(getToolTipTextByAction(myCurrentAction)); } @@ -533,6 +531,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS this(action, activeIcon, activeIcon); } + @Override public void actionPerformed(final ActionEvent e) { AnAction action = myAlternativeAction != null && BitUtil.isSet(e.getModifiers(), InputEvent.ALT_MASK) ? myAlternativeAction : myAction; @@ -557,6 +556,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS myButton.setIcons(active, inactive, hovered); } + @Override public void setToolTipText(final String text) { myButton.setToolTipText(text); } @@ -588,15 +588,17 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS } private abstract class HideSideAction extends AnAction implements DumbAware { - @NonNls public static final String HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID; + @NonNls static final String HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID; public HideSideAction() { copyFrom(ActionManager.getInstance().getAction(HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID)); getTemplatePresentation().setText(UIBundle.message("tool.window.hideSide.action.name")); } + @Override public abstract void actionPerformed(@NotNull final AnActionEvent e); + @Override public final void update(@NotNull final AnActionEvent event) { final Presentation presentation = event.getPresentation(); presentation.setEnabled(myInfo.isVisible()); @@ -604,13 +606,14 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS } private abstract class HideAction extends AnAction implements DumbAware { - @NonNls public static final String HIDE_ACTIVE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_WINDOW_ACTION_ID; + @NonNls static final String HIDE_ACTIVE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_WINDOW_ACTION_ID; public HideAction() { copyFrom(ActionManager.getInstance().getAction(HIDE_ACTIVE_WINDOW_ACTION_ID)); getTemplatePresentation().setText(UIBundle.message("tool.window.hide.action.name")); } + @Override public final void update(@NotNull final AnActionEvent event) { final Presentation presentation = event.getPresentation(); presentation.setEnabled(myInfo.isVisible()); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java index 3c89e2642939..29f8cbeae9ca 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java @@ -53,9 +53,9 @@ import java.beans.PropertyChangeListener; import java.util.*; import java.util.List; -@SuppressWarnings({"ConstantConditions"}) +@SuppressWarnings("ConstantConditions") public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { - private final Map myToolWindows = new HashMap(); + private final Map myToolWindows = new HashMap<>(); private final Project myProject; public ToolWindowHeadlessManagerImpl(Project project) { @@ -75,12 +75,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { MockToolWindow tw = new MockToolWindow(myProject); myToolWindows.put(id, tw); if (parentDisposable != null) { - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - unregisterToolWindow(id); - } - }); + Disposer.register(parentDisposable, () -> unregisterToolWindow(id)); } return tw; } @@ -90,7 +85,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode) { return doRegisterToolWindow(id, parentDisposable); } @@ -106,7 +101,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean canCloseContents) { return doRegisterToolWindow(id, parentDisposable); @@ -139,7 +134,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, - final Disposable parentDisposable, final boolean dumbAware) { + @NotNull final Disposable parentDisposable, final boolean dumbAware) { return doRegisterToolWindow(id, parentDisposable); } @@ -148,7 +143,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { public ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean secondary) { return doRegisterToolWindow(id, parentDisposable); @@ -222,16 +217,16 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { } @Override - public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) { + public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) { } @Override - public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable) { + public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener, @NotNull Disposable parentDisposable) { } @Override - public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) { + public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) { } @Override @@ -270,9 +265,10 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { public void hideToolWindow(@NotNull final String id, final boolean hideSide) { } + @NotNull @Override public List getIdsOn(@NotNull final ToolWindowAnchor anchor) { - return new ArrayList(); + return new ArrayList<>(); } public static class MockToolWindow implements ToolWindowEx { @@ -330,7 +326,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { } @Override - public void setAnchor(ToolWindowAnchor anchor, @Nullable Runnable runnable) { + public void setAnchor(@NotNull ToolWindowAnchor anchor, @Nullable Runnable runnable) { } @Override @@ -367,7 +363,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { } @Override - public void setType(ToolWindowType type, @Nullable Runnable runnable) { + public void setType(@NotNull ToolWindowType type, @Nullable Runnable runnable) { } @Override @@ -500,7 +496,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { private static class MockContentManager implements ContentManager { private final EventDispatcher myDispatcher = EventDispatcher.create(ContentManagerListener.class); - private final List myContents = new ArrayList(); + private final List myContents = new ArrayList<>(); private Content mySelected; @NotNull diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java index d58f6ce9a646..c97831818eec 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java @@ -60,11 +60,11 @@ import java.util.Set; * @author Vladimir Kondratyev */ public final class ToolWindowImpl implements ToolWindowEx { - private final PropertyChangeSupport myChangeSupport; + private final PropertyChangeSupport myChangeSupport = new PropertyChangeSupport(this); private final ToolWindowManagerImpl myToolWindowManager; private final String myId; private final JComponent myComponent; - private boolean myAvailable; + private boolean myAvailable = true; private final ContentManager myContentManager; private Icon myIcon; private String myStripeTitle; @@ -74,18 +74,18 @@ public final class ToolWindowImpl implements ToolWindowEx { private InternalDecorator myDecorator; - private boolean myHideOnEmptyContent = false; + private boolean myHideOnEmptyContent; private boolean myPlaceholderMode; private ToolWindowFactory myContentFactory; - private static Set FORWARD_TRAVERSAL_KEYSTROKES = new HashSet(Arrays.asList( - new KeyStroke[] { + private static final Set FORWARD_TRAVERSAL_KEYSTROKES = new HashSet<>(Arrays.asList( + new KeyStroke[]{ KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0) } )); - private static Set BACKWARD_TRAVERSAL_KEYSTROKES = new HashSet(Arrays.asList( - new KeyStroke[] { + private static final Set BACKWARD_TRAVERSAL_KEYSTROKES = new HashSet<>(Arrays.asList( + new KeyStroke[]{ KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK) } )); @@ -102,16 +102,13 @@ public final class ToolWindowImpl implements ToolWindowEx { private static final Logger LOG = Logger.getInstance(ToolWindowImpl.class); - ToolWindowImpl(final ToolWindowManagerImpl toolWindowManager, final String id, boolean canCloseContent, @Nullable final JComponent component) { + ToolWindowImpl(@NotNull ToolWindowManagerImpl toolWindowManager, @NotNull String id, boolean canCloseContent, @Nullable final JComponent component) { myToolWindowManager = toolWindowManager; - myChangeSupport = new PropertyChangeSupport(this); myId = id; - myAvailable = true; final ContentFactory contentFactory = ServiceManager.getService(ContentFactory.class); myContentUI = new ToolWindowContentUi(this); - myContentManager = - contentFactory.createContentManager(myContentUI, canCloseContent, toolWindowManager.getProject()); + myContentManager = contentFactory.createContentManager(myContentUI, canCloseContent, toolWindowManager.getProject()); if (component != null) { final Content content = contentFactory.createContent(component, "", false); @@ -224,7 +221,7 @@ public final class ToolWindowImpl implements ToolWindowEx { public ActionCallback getReady(@NotNull final Object requestor) { final ActionCallback result = new ActionCallback(); myShowing.getReady(this).doWhenDone(() -> { - ArrayList cmd = new ArrayList(); + ArrayList cmd = new ArrayList<>(); cmd.add(new FinalizableCommand(null) { @Override public void run() { @@ -268,7 +265,7 @@ public final class ToolWindowImpl implements ToolWindowEx { } @Override - public final void setAnchor(final ToolWindowAnchor anchor, @Nullable final Runnable runnable) { + public final void setAnchor(@NotNull final ToolWindowAnchor anchor, @Nullable final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.setToolWindowAnchor(myId, anchor); if (runnable != null) { @@ -330,7 +327,7 @@ public final class ToolWindowImpl implements ToolWindowEx { } @Override - public final void setType(final ToolWindowType type, @Nullable final Runnable runnable) { + public final void setType(@NotNull final ToolWindowType type, @Nullable final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.setToolWindowType(myId, type); if (runnable != null) { @@ -416,6 +413,7 @@ public final class ToolWindowImpl implements ToolWindowEx { //return getSelectedContent().getIcon(); } + @NotNull public final String getId() { return myId; } @@ -531,11 +529,11 @@ public final class ToolWindowImpl implements ToolWindowEx { return myContentManager.isDisposed(); } - public boolean isPlaceholderMode() { + boolean isPlaceholderMode() { return myPlaceholderMode; } - public void setPlaceholderMode(final boolean placeholderMode) { + void setPlaceholderMode(final boolean placeholderMode) { myPlaceholderMode = placeholderMode; } @@ -546,7 +544,7 @@ public final class ToolWindowImpl implements ToolWindowEx { } @NotNull - public ActionCallback setActivation(@NotNull ActionCallback activation) { + ActionCallback setActivation(@NotNull ActionCallback activation) { if (!myActivation.isProcessed() && !myActivation.equals(activation)) { myActivation.setRejected(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 977407222522..1fcbb33e3af1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -95,26 +95,26 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final Project myProject; private final WindowManagerEx myWindowManager; private final EventDispatcher myDispatcher = EventDispatcher.create(ToolWindowManagerListener.class); - private final DesktopLayout myLayout; - private final Map myId2InternalDecorator; - private final Map myId2FloatingDecorator; - private final Map myId2WindowedDecorator; - private final Map myId2StripeButton; - private final Map myId2FocusWatcher; + private final DesktopLayout myLayout = new DesktopLayout(); + private final Map myId2InternalDecorator = new HashMap<>(); + private final Map myId2FloatingDecorator = new HashMap<>(); + private final Map myId2WindowedDecorator = new HashMap<>(); + private final Map myId2StripeButton = new HashMap<>(); + private final Map myId2FocusWatcher = new HashMap<>(); private final Set myDumbAwareIds = Collections.synchronizedSet(ContainerUtil.newTroveSet()); - private final EditorComponentFocusWatcher myEditorComponentFocusWatcher; - private final MyToolWindowPropertyChangeListener myToolWindowPropertyChangeListener; - private final InternalDecoratorListener myInternalDecoratorListener; + private final EditorComponentFocusWatcher myEditorComponentFocusWatcher = new EditorComponentFocusWatcher(); + private final MyToolWindowPropertyChangeListener myToolWindowPropertyChangeListener = new MyToolWindowPropertyChangeListener(); + private final InternalDecoratorListener myInternalDecoratorListener = new MyInternalDecoratorListener(); private boolean myEditorWasActive; - private final ActiveStack myActiveStack; - private final SideStack mySideStack; + private final ActiveStack myActiveStack = new ActiveStack(); + private final SideStack mySideStack = new SideStack(); private ToolWindowsPane myToolWindowsPane; private IdeFrameImpl myFrame; - private DesktopLayout myLayoutToRestoreLater = null; + private DesktopLayout myLayoutToRestoreLater; @NonNls private static final String EDITOR_ELEMENT = "editor"; @NonNls private static final String ACTIVE_ATTR_VALUE = "active"; @NonNls private static final String FRAME_ELEMENT = "frame"; @@ -127,8 +127,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final FileEditorManager myFileEditorManager; private final LafManager myLafManager; - private final Map myWindow2Balloon = new HashMap(); - private Pair myMaximizedToolwindowSize = null; + private final Map myWindow2Balloon = new HashMap<>(); private KeyState myCurrentState = KeyState.waiting; private final Alarm myWaiterForSecondPress = new Alarm(); @@ -139,7 +138,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }; private final PropertyChangeListener myFocusListener; - public boolean isToolWindowRegistered(String id) { + boolean isToolWindowRegistered(@NotNull String id) { return myLayout.isToolWindowRegistered(id); } @@ -148,7 +147,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } private final Alarm myUpdateHeadersAlarm = new Alarm(); - private final Runnable myUpdateHeadersRunnable = () -> updateToolWindowHeaders(); /** * invoked by reflection @@ -182,22 +180,8 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }, project); } - myLayout = new DesktopLayout(); myLayout.copyFrom(windowManagerEx.getLayout()); - myId2InternalDecorator = new HashMap(); - myId2FloatingDecorator = new HashMap(); - myId2WindowedDecorator = new HashMap(); - myId2StripeButton = new HashMap(); - myId2FocusWatcher = new HashMap(); - - myEditorComponentFocusWatcher = new EditorComponentFocusWatcher(); - myToolWindowPropertyChangeListener = new MyToolWindowPropertyChangeListener(); - myInternalDecoratorListener = new MyInternalDecoratorListener(); - - myActiveStack = new ActiveStack(); - mySideStack = new SideStack(); - project.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() { @Override public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) { @@ -220,13 +204,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } }); - myFocusListener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if ("focusOwner".equals(evt.getPropertyName())) { - myUpdateHeadersAlarm.cancelAllRequests(); - myUpdateHeadersAlarm.addRequest(myUpdateHeadersRunnable, 50); - } + myFocusListener = evt -> { + if ("focusOwner".equals(evt.getPropertyName())) { + myUpdateHeadersAlarm.cancelAllRequests(); + myUpdateHeadersAlarm.addRequest(this::updateToolWindowHeaders, 50); } }; KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener(myFocusListener); @@ -253,7 +234,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }); } - public boolean dispatchKeyEvent(KeyEvent e) { + public boolean dispatchKeyEvent(@NotNull KeyEvent e) { if (e.getKeyCode() != KeyEvent.VK_CONTROL && e.getKeyCode() != KeyEvent.VK_ALT && e.getKeyCode() != KeyEvent.VK_SHIFT && @@ -299,8 +280,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return false; } - public static Set getActivateToolWindowVKs() { - if (ApplicationManager.getApplication() == null) return new HashSet(); + @NotNull + private static Set getActivateToolWindowVKs() { + if (ApplicationManager.getApplication() == null) return new HashSet<>(); Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); Shortcut[] baseShortcut = keymap.getShortcuts("ActivateProjectToolWindow"); @@ -373,7 +355,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @Override public void disposeComponent() { - for (String id : new ArrayList(myId2StripeButton.keySet())) { + for (String id : new ArrayList<>(myId2StripeButton.keySet())) { unregisterToolWindow(id); } @@ -390,21 +372,17 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements UIManager.addPropertyChangeListener(uiManagerPropertyListener); myLafManager.addLafManagerListener(lafManagerListener); - Disposer.register(myProject, new Disposable() { - @Override - public void dispose() { - UIManager.removePropertyChangeListener(uiManagerPropertyListener); - myLafManager.removeLafManagerListener(lafManagerListener); - } + Disposer.register(myProject, () -> { + UIManager.removePropertyChangeListener(uiManagerPropertyListener); + myLafManager.removeLafManagerListener(lafManagerListener); }); myFrame = myWindowManager.allocateFrame(myProject); LOG.assertTrue(myFrame != null); - final ArrayList commandsList = new ArrayList(); - myToolWindowsPane = new ToolWindowsPane(myFrame, this); Disposer.register(myProject, myToolWindowsPane); ((IdeRootPane)myFrame.getRootPane()).setToolWindowsPane(myToolWindowsPane); + List commandsList = new ArrayList<>(); appendUpdateToolWindowsPaneCmd(commandsList); myFrame.setTitle(FrameTitleBuilder.getInstance().getProjectTitle(myProject)); @@ -432,13 +410,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }; myProject.getMessageBus().connect().subscribe(DumbService.DUMB_MODE, dumbModeListener); - StartupManager.getInstance(myProject).registerPostStartupActivity(new DumbAwareRunnable() { - @Override - public void run() { - registerToolWindowsFromBeans(); - if (DumbService.getInstance(myProject).isDumb()) { - disableStripeButtons(); - } + StartupManager.getInstance(myProject).registerPostStartupActivity((DumbAwareRunnable)() -> { + registerToolWindowsFromBeans(); + if (DumbService.getInstance(myProject).isDumb()) { + disableStripeButtons(); } }); @@ -446,7 +421,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (e instanceof KeyEvent) { dispatchKeyEvent((KeyEvent)e); } - if (e instanceof WindowEvent && (e.getID() == WindowEvent.WINDOW_LOST_FOCUS) && e.getSource() == myFrame) { + if (e instanceof WindowEvent && e.getID() == WindowEvent.WINDOW_LOST_FOCUS && e.getSource() == myFrame) { resetHoldState(); } return false; @@ -467,7 +442,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - private JComponent createEditorComponent(Project project) { + private static JComponent createEditorComponent(@NotNull Project project) { return FrameEditorComponentProvider.EP.getExtensions()[0].createEditorComponent(project); } @@ -542,19 +517,16 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements WindowInfoImpl info = getInfo(bean.id); if (!info.isSplit() && bean.secondary && !info.wasRead()) { - toolWindow.setSplitMode(bean.secondary, null); + toolWindow.setSplitMode(true, null); } final ActionCallback activation = toolWindow.setActivation(new ActionCallback()); - final DumbAwareRunnable runnable = new DumbAwareRunnable() { - @Override - public void run() { - if (toolWindow.isDisposed()) return; + final DumbAwareRunnable runnable = () -> { + if (toolWindow.isDisposed()) return; - toolWindow.ensureContentInitialized(); - activation.setDone(); - } + toolWindow.ensureContentInitialized(); + activation.setDone(); }; if (ApplicationManager.getApplication().isUnitTestMode()) { runnable.run(); @@ -566,7 +538,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @Override public void projectClosed() { - final ArrayList commandsList = new ArrayList(); final String[] ids = getToolWindowIds(); // Remove ToolWindowsPane @@ -574,6 +545,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements ((IdeRootPane)myFrame.getRootPane()).setToolWindowsPane(null); myWindowManager.releaseFrame(myFrame); } + List commandsList = new ArrayList<>(); appendUpdateToolWindowsPaneCmd(commandsList); // Hide all tool windows @@ -591,18 +563,18 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } @Override - public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) { - myDispatcher.addListener(l); + public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) { + myDispatcher.addListener(listener); } @Override - public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable) { - myDispatcher.addListener(l, parentDisposable); + public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener, @NotNull Disposable parentDisposable) { + myDispatcher.addListener(listener, parentDisposable); } @Override - public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) { - myDispatcher.removeListener(l); + public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) { + myDispatcher.removeListener(listener); } /** @@ -641,7 +613,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements final ExpirableRunnable runnable = new ExpirableRunnable.ForProject(myProject) { @Override public void run() { - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); activateEditorComponentImpl(commandList, forced); execute(commandList); } @@ -669,15 +641,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - private void activateEditorComponentImpl(List commandList, final boolean forced) { + private void activateEditorComponentImpl(@NotNull List commandList, final boolean forced) { final String active = getActiveToolWindowId(); // Now we have to request focus into most recent focused editor appendRequestFocusInEditorComponentCmd(commandList, forced).doWhenDone(() -> { - final ArrayList commandList12 = new ArrayList(); - if (LOG.isDebugEnabled()) { LOG.debug("editor activated"); } + List commandList12 = new ArrayList<>(); deactivateWindows(null, commandList12); myActiveStack.clear(); @@ -688,9 +659,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @NotNull @Override public ActionCallback run() { - final ArrayList commandList1 = new ArrayList(); + List commandList1 = new ArrayList<>(); - final WindowInfoImpl toReactivate = getInfo(active); + final WindowInfoImpl toReactivate = active == null ? null : getInfo(active); final boolean reactivateLastActive = toReactivate != null && !isToHideOnDeactivation(toReactivate); deactivateWindows(reactivateLastActive ? active : null, commandList1); execute(commandList1); @@ -714,7 +685,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }); } - private void deactivateWindows( @Nullable String idToIgnore, final List commandList) { + private void deactivateWindows(@Nullable String idToIgnore, @NotNull List commandList) { final WindowInfoImpl[] infos = myLayout.getInfos(); for (final WindowInfoImpl info : infos) { if (idToIgnore != null && idToIgnore.equals(info.getId())) { @@ -736,11 +707,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements * * @param dirtyMode if true then all UI operations are performed in "dirty" mode. * It means that UI isn't validated and repainted just after each add/remove operation. - * @see ToolWindowManagerImpl#prepareForActivation */ - private void showAndActivate(final String id, + private void showAndActivate(@NotNull String id, final boolean dirtyMode, - List commandsList, + @NotNull List commandsList, boolean autoFocusContents, boolean forcedFocusRequest) { if (!getToolWindow(id).isAvailable()) { @@ -766,7 +736,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - void activateToolWindow(final String id, boolean forced, boolean autoFocusContents) { + void activateToolWindow(@NotNull String id, boolean forced, boolean autoFocusContents) { if (LOG.isDebugEnabled()) { LOG.debug("enter: activateToolWindow(" + id + ")"); } @@ -776,13 +746,13 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return; } - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); activateToolWindowImpl(id, commandList, forced, autoFocusContents); execute(commandList); } - private void activateToolWindowImpl(final String id, - List commandList, + private void activateToolWindowImpl(@NotNull String id, + @NotNull List commandList, boolean forced, boolean autoFocusContents) { if (!FocusManagerImpl.getInstance().isUnforcedRequestAllowed() && !forced) return; @@ -810,7 +780,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements * * @throws IllegalStateException if tool window isn't installed. */ - private void checkId(final String id) { + private void checkId(@NotNull String id) { if (!myLayout.isToolWindowRegistered(id)) { throw new IllegalStateException("window with id=\"" + id + "\" isn't registered"); } @@ -822,7 +792,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements * @param id id of the tool window to be deactivated. * @param shouldHide if true then also hides specified tool window. */ - private void deactivateToolWindowImpl(final String id, final boolean shouldHide, final List commandsList) { + private void deactivateToolWindowImpl(@NotNull String id, final boolean shouldHide, @NotNull List commandsList) { if (LOG.isDebugEnabled()) { LOG.debug("enter: deactivateToolWindowImpl(" + id + "," + shouldHide + ")"); } @@ -887,37 +857,38 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @return floating decorator for the tool window with specified ID. */ - private FloatingDecorator getFloatingDecorator(final String id) { + private FloatingDecorator getFloatingDecorator(@NotNull String id) { return myId2FloatingDecorator.get(id); } /** * @return windowed decorator for the tool window with specified ID. */ - private WindowedDecorator getWindowedDecorator(String id) { + private WindowedDecorator getWindowedDecorator(@NotNull String id) { return myId2WindowedDecorator.get(id); } /** * @return internal decorator for the tool window with specified ID. */ - private InternalDecorator getInternalDecorator(final String id) { + private InternalDecorator getInternalDecorator(@NotNull String id) { return myId2InternalDecorator.get(id); } /** * @return tool button for the window with specified ID. */ - private StripeButton getStripeButton(final String id) { + private StripeButton getStripeButton(@NotNull String id) { return myId2StripeButton.get(id); } /** * @return info for the tool window with specified ID. */ - private WindowInfoImpl getInfo(final String id) { + private WindowInfoImpl getInfo(@NotNull String id) { return myLayout.getInfo(id, true); } @Override + @NotNull public List getIdsOn(@NotNull final ToolWindowAnchor anchor) { return myLayout.getVisibleIdsOn(anchor, this); } @@ -931,12 +902,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return decorator != null ? decorator.getToolWindow() : null; } - void showToolWindow(final String id) { + void showToolWindow(@NotNull String id) { if (LOG.isDebugEnabled()) { LOG.debug("enter: showToolWindow(" + id + ")"); } ApplicationManager.getApplication().assertIsDispatchThread(); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); showToolWindowImpl(id, false, commandList); execute(commandList); } @@ -946,12 +917,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements hideToolWindow(id, hideSide, true); } - public void hideToolWindow(final String id, final boolean hideSide, final boolean moveFocus) { + public void hideToolWindow(@NotNull String id, final boolean hideSide, final boolean moveFocus) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); final WindowInfoImpl info = getInfo(id); if (!info.isVisible()) return; - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); final boolean wasActive = info.isActive(); // hide and deactivate @@ -1024,7 +995,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } else { final String toBeActivatedId = myActiveStack.pop(); - if (toBeActivatedId != null && (getInfo(toBeActivatedId).isVisible() || isStackEnabled())) { + if (getInfo(toBeActivatedId).isVisible() || isStackEnabled()) { activateToolWindowImpl(toBeActivatedId, commandList, false, true); } else { @@ -1044,7 +1015,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @param dirtyMode if true then all UI operations are performed in dirty mode. */ - private void showToolWindowImpl(final String id, final boolean dirtyMode, final List commandsList) { + private void showToolWindowImpl(@NotNull String id, final boolean dirtyMode, @NotNull List commandsList) { final WindowInfoImpl toBeShownInfo = getInfo(id); if (toBeShownInfo.isVisible() || !getToolWindow(id).isAvailable()) { return; @@ -1184,7 +1155,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements public ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean secondary) { ToolWindow window = registerToolWindow(id, null, anchor, secondary, canCloseContent, canWorkInDumbMode); @@ -1226,7 +1197,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements final StripeButton button = new StripeButton(decorator, myToolWindowsPane); myId2StripeButton.put(id, button); - List commandsList = new ArrayList(); + List commandsList = new ArrayList<>(); appendAddButtonCmd(button, info, commandsList); if (canWorkInDumbMode) { @@ -1260,12 +1231,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @NotNull private ToolWindow registerDisposable(@NotNull final String id, @NotNull final Disposable parentDisposable, @NotNull ToolWindow window) { - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - unregisterToolWindow(id); - } - }); + Disposer.register(parentDisposable, () -> unregisterToolWindow(id)); return window; } @@ -1284,7 +1250,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements // Save recent appearance of tool window myLayout.unregister(id); // Remove decorator and tool button from the screen - final ArrayList commandsList = new ArrayList(); + List commandsList = new ArrayList<>(); if (info.isVisible()) { info.setVisible(false); if (info.isFloating()) { @@ -1338,7 +1304,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @Override public void setLayout(@NotNull final DesktopLayout layout) { ApplicationManager.getApplication().assertIsDispatchThread(); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); // hide tool window that are invisible in new layout final WindowInfoImpl[] currentInfos = myLayout.getInfos(); for (final WindowInfoImpl currentInfo : currentInfos) { @@ -1400,7 +1366,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @Override public void invokeLater(@NotNull final Runnable runnable) { - List commandList = new ArrayList(); + List commandList = new ArrayList<>(); commandList.add(new InvokeLaterCmd(runnable, myWindowManager.getCommandProcessor())); execute(commandList); } @@ -1480,19 +1446,16 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }); listenerWrapper.myBalloon = balloon; myWindow2Balloon.put(toolWindowId, balloon); - Disposer.register(balloon, new Disposable() { - @Override - public void dispose() { - window.setPlaceholderMode(false); - stripe.updatePresentation(); - stripe.revalidate(); - stripe.repaint(); - myWindow2Balloon.remove(toolWindowId); - } + Disposer.register(balloon, () -> { + window.setPlaceholderMode(false); + stripe.updatePresentation(); + stripe.revalidate(); + stripe.repaint(); + myWindow2Balloon.remove(toolWindowId); }); Disposer.register(getProject(), balloon); - execute(new ArrayList(Arrays.asList(new FinalizableCommand(null) { + execute(new ArrayList<>(Collections.singletonList(new FinalizableCommand(null) { @Override public void run() { final StripeButton button = stripe.getButtonFor(toolWindowId); @@ -1550,7 +1513,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }; if (!button.isValid()) { - SwingUtilities.invokeLater(() -> show.run()); + SwingUtilities.invokeLater(show); } else { show.run(); @@ -1573,27 +1536,28 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return splitters != null; } - ToolWindowAnchor getToolWindowAnchor(final String id) { + @NotNull + ToolWindowAnchor getToolWindowAnchor(@NotNull String id) { checkId(id); return getInfo(id).getAnchor(); } - void setToolWindowAnchor(final String id, final ToolWindowAnchor anchor) { + void setToolWindowAnchor(@NotNull String id, @NotNull ToolWindowAnchor anchor) { ApplicationManager.getApplication().assertIsDispatchThread(); setToolWindowAnchor(id, anchor, -1); } - void setToolWindowAnchor(final String id, final ToolWindowAnchor anchor, final int order) { + private void setToolWindowAnchor(@NotNull String id, @NotNull ToolWindowAnchor anchor, final int order) { ApplicationManager.getApplication().assertIsDispatchThread(); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); setToolWindowAnchorImpl(id, anchor, order, commandList); execute(commandList); } - private void setToolWindowAnchorImpl(final String id, - final ToolWindowAnchor anchor, + private void setToolWindowAnchorImpl(@NotNull String id, + @NotNull ToolWindowAnchor anchor, final int order, - final ArrayList commandsList) { + @NotNull List commandsList) { checkId(id); final WindowInfoImpl info = getInfo(id); if (anchor == info.getAnchor() && order == info.getOrder()) { @@ -1630,42 +1594,42 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - boolean isSplitMode(String id) { + boolean isSplitMode(@NotNull String id) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); return getInfo(id).isSplit(); } @NotNull - ToolWindowContentUiType getContentUiType(String id) { + ToolWindowContentUiType getContentUiType(@NotNull String id) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); return getInfo(id).getContentUiType(); } - void setSideTool(String id, boolean isSide) { - final ArrayList commandList = new ArrayList(); + void setSideTool(@NotNull String id, boolean isSide) { + List commandList = new ArrayList<>(); setSplitModeImpl(id, isSide, commandList); execute(commandList); } - public void setContentUiType(String id, @NotNull ToolWindowContentUiType type) { - final ArrayList commandList = new ArrayList(); + void setContentUiType(@NotNull String id, @NotNull ToolWindowContentUiType type) { checkId(id); WindowInfoImpl info = getInfo(id); info.setContentUiType(type); + List commandList = new ArrayList<>(); appendApplyWindowInfoCmd(info, commandList); execute(commandList); } - void setSideToolAndAnchor(String id, ToolWindowAnchor anchor, int order, boolean isSide) { - final ArrayList commandList = new ArrayList(); + void setSideToolAndAnchor(@NotNull String id, @NotNull ToolWindowAnchor anchor, int order, boolean isSide) { setToolWindowAnchor(id, anchor, order); + List commandList = new ArrayList<>(); setSplitModeImpl(id, isSide, commandList); execute(commandList); } - private void setSplitModeImpl(final String id, final boolean isSplit, final ArrayList commandList) { + private void setSplitModeImpl(@NotNull String id, final boolean isSplit, @NotNull List commandList) { checkId(id); final WindowInfoImpl info = getInfo(id); if (isSplit == info.isSplit()) { @@ -1688,18 +1652,18 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements commandList.add(myToolWindowsPane.createUpdateButtonPositionCmd(id, myWindowManager.getCommandProcessor())); } - ToolWindowType getToolWindowInternalType(final String id) { + ToolWindowType getToolWindowInternalType(@NotNull String id) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); return getInfo(id).getInternalType(); } - ToolWindowType getToolWindowType(final String id) { + ToolWindowType getToolWindowType(@NotNull String id) { checkId(id); return getInfo(id).getType(); } - private void fireToolWindowRegistered(final String id) { + private void fireToolWindowRegistered(@NotNull String id) { myDispatcher.getMulticaster().toolWindowRegistered(id); } @@ -1707,31 +1671,31 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myDispatcher.getMulticaster().stateChanged(); } - boolean isToolWindowActive(final String id) { + boolean isToolWindowActive(@NotNull String id) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); return getInfo(id).isActive(); } - boolean isToolWindowAutoHide(final String id) { + boolean isToolWindowAutoHide(@NotNull String id) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); return getInfo(id).isAutoHide(); } - boolean isToolWindowVisible(final String id) { + boolean isToolWindowVisible(@NotNull String id) { checkId(id); return getInfo(id).isVisible(); } - void setToolWindowAutoHide(final String id, final boolean autoHide) { + void setToolWindowAutoHide(@NotNull String id, final boolean autoHide) { ApplicationManager.getApplication().assertIsDispatchThread(); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); setToolWindowAutoHideImpl(id, autoHide, commandList); execute(commandList); } - private void setToolWindowAutoHideImpl(final String id, final boolean autoHide, final ArrayList commandsList) { + private void setToolWindowAutoHideImpl(@NotNull String id, final boolean autoHide, @NotNull List commandsList) { checkId(id); final WindowInfoImpl info = getInfo(id); if (info.isAutoHide() == autoHide) { @@ -1745,14 +1709,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - void setToolWindowType(final String id, final ToolWindowType type) { + void setToolWindowType(@NotNull String id, @NotNull ToolWindowType type) { ApplicationManager.getApplication().assertIsDispatchThread(); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); setToolWindowTypeImpl(id, type, commandList); execute(commandList); } - private void setToolWindowTypeImpl(final String id, final ToolWindowType type, final ArrayList commandsList) { + private void setToolWindowTypeImpl(@NotNull String id, @NotNull ToolWindowType type, @NotNull List commandsList) { checkId(id); final WindowInfoImpl info = getInfo(id); if (info.getType() == type) { @@ -1782,7 +1746,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - private void appendApplyWindowInfoCmd(final WindowInfoImpl info, final List commandsList) { + private void appendApplyWindowInfoCmd(@NotNull WindowInfoImpl info, @NotNull List commandsList) { final StripeButton button = getStripeButton(info.getId()); final InternalDecorator decorator = getInternalDecorator(info.getId()); commandsList.add(new ApplyWindowInfoCmd(info, button, decorator, myWindowManager.getCommandProcessor())); @@ -1791,10 +1755,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @see ToolWindowsPane#createAddDecoratorCmd */ - private void appendAddDecoratorCmd(final InternalDecorator decorator, - final WindowInfoImpl info, + private void appendAddDecoratorCmd(@NotNull InternalDecorator decorator, + @NotNull WindowInfoImpl info, final boolean dirtyMode, - final List commandsList) { + @NotNull List commandsList) { final CommandProcessor commandProcessor = myWindowManager.getCommandProcessor(); final FinalizableCommand command = myToolWindowsPane.createAddDecoratorCmd(decorator, info, dirtyMode, commandProcessor); commandsList.add(command); @@ -1803,17 +1767,17 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @see ToolWindowsPane#createRemoveDecoratorCmd */ - private void appendRemoveDecoratorCmd(final String id, final boolean dirtyMode, final List commandsList) { + private void appendRemoveDecoratorCmd(@NotNull String id, final boolean dirtyMode, @NotNull List commandsList) { final FinalizableCommand command = myToolWindowsPane.createRemoveDecoratorCmd(id, dirtyMode, myWindowManager.getCommandProcessor()); commandsList.add(command); } - private void appendRemoveFloatingDecoratorCmd(final WindowInfoImpl info, final List commandsList) { + private void appendRemoveFloatingDecoratorCmd(@NotNull WindowInfoImpl info, @NotNull List commandsList) { final RemoveFloatingDecoratorCmd command = new RemoveFloatingDecoratorCmd(info); commandsList.add(command); } - private void appendRemoveWindowedDecoratorCmd(final WindowInfoImpl info, final List commandsList) { + private void appendRemoveWindowedDecoratorCmd(@NotNull WindowInfoImpl info, @NotNull List commandsList) { final RemoveWindowedDecoratorCmd command = new RemoveWindowedDecoratorCmd(info); commandsList.add(command); } @@ -1821,7 +1785,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @see ToolWindowsPane#createAddButtonCmd */ - private void appendAddButtonCmd(final StripeButton button, final WindowInfoImpl info, final List commandsList) { + private void appendAddButtonCmd(final StripeButton button, @NotNull WindowInfoImpl info, @NotNull List commandsList) { final Comparator comparator = myLayout.comparator(info.getAnchor()); final CommandProcessor commandProcessor = myWindowManager.getCommandProcessor(); final FinalizableCommand command = myToolWindowsPane.createAddButtonCmd(button, info, comparator, commandProcessor); @@ -1831,7 +1795,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @see ToolWindowsPane#createAddButtonCmd */ - private void appendRemoveButtonCmd(final String id, final List commandsList) { + private void appendRemoveButtonCmd(@NotNull String id, @NotNull List commandsList) { final FinalizableCommand command = myToolWindowsPane.createRemoveButtonCmd(id, myWindowManager.getCommandProcessor()); commandsList.add(command); } @@ -1855,7 +1819,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @see ToolWindowsPane#createSetEditorComponentCmd */ - public void appendSetEditorComponentCmd(@Nullable final JComponent component, final List commandsList) { + private void appendSetEditorComponentCmd(@Nullable final JComponent component, @NotNull List commandsList) { final CommandProcessor commandProcessor = myWindowManager.getCommandProcessor(); final FinalizableCommand command = myToolWindowsPane.createSetEditorComponentCmd(component, commandProcessor); commandsList.add(command); @@ -1885,36 +1849,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return splitters != null ? splitters : fem.getSplitters(); } - /** - * @return true if tool window with the specified id - * is floating and has modal showing child dialog. Such windows should not be closed - * when auto-hide windows are gone. - */ - private boolean hasModalChild(final WindowInfoImpl info) { - if (!info.isVisible() || !info.isFloating()) { - return false; - } - final FloatingDecorator decorator = getFloatingDecorator(info.getId()); - LOG.assertTrue(decorator != null); - return isModalOrHasModalChild(decorator); - } - - private static boolean isModalOrHasModalChild(final Window window) { - if (window instanceof Dialog) { - final Dialog dialog = (Dialog)window; - if (dialog.isModal() && dialog.isShowing()) { - return true; - } - final Window[] ownedWindows = dialog.getOwnedWindows(); - for (int i = ownedWindows.length - 1; i >= 0; i--) { - if (isModalOrHasModalChild(ownedWindows[i])) { - return true; - } - } - } - return false; - } - @Override public void clearSideStack() { mySideStack.clear(); @@ -2000,14 +1934,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - public void setDefaultContentUiType(ToolWindowImpl toolWindow, @NotNull ToolWindowContentUiType type) { + void setDefaultContentUiType(@NotNull ToolWindowImpl toolWindow, @NotNull ToolWindowContentUiType type) { final WindowInfoImpl info = getInfo(toolWindow.getId()); if (info.wasRead()) return; toolWindow.setContentUiType(type, null); } - public void stretchWidth(ToolWindowImpl toolWindow, int value) { + void stretchWidth(@NotNull ToolWindowImpl toolWindow, int value) { myToolWindowsPane.stretchWidth(toolWindow, value); } @@ -2021,7 +1955,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myToolWindowsPane.setMaximized(wnd, maximized); } - public void stretchHeight(ToolWindowImpl toolWindow, int value) { + void stretchHeight(ToolWindowImpl toolWindow, int value) { myToolWindowsPane.stretchHeight(toolWindow, value); } @@ -2029,7 +1963,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private Balloon myBalloon; private final HyperlinkListener myListener; - public BalloonHyperlinkListener(HyperlinkListener listener) { + BalloonHyperlinkListener(HyperlinkListener listener) { myListener = listener; } @@ -2054,7 +1988,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * Creates floating decorator for specified internal decorator. */ - private AddFloatingDecoratorCmd(final InternalDecorator decorator, final WindowInfoImpl info) { + private AddFloatingDecoratorCmd(@NotNull InternalDecorator decorator, @NotNull WindowInfoImpl info) { super(myWindowManager.getCommandProcessor()); myFloatingDecorator = new FloatingDecorator(myFrame, info.copy(), decorator); myId2FloatingDecorator.put(info.getId(), myFloatingDecorator); @@ -2093,7 +2027,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final class RemoveFloatingDecoratorCmd extends FinalizableCommand { private final FloatingDecorator myFloatingDecorator; - private RemoveFloatingDecoratorCmd(final WindowInfoImpl info) { + private RemoveFloatingDecoratorCmd(@NotNull WindowInfoImpl info) { super(myWindowManager.getCommandProcessor()); myFloatingDecorator = getFloatingDecorator(info.getId()); myId2FloatingDecorator.remove(info.getId()); @@ -2126,7 +2060,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * Creates windowed decorator for specified internal decorator. */ - private AddWindowedDecoratorCmd(final InternalDecorator decorator, final WindowInfoImpl info) { + private AddWindowedDecoratorCmd(@NotNull InternalDecorator decorator, @NotNull WindowInfoImpl info) { super(myWindowManager.getCommandProcessor()); myWindowedDecorator = new WindowedDecorator(myProject, info.copy(), decorator); Window window = myWindowedDecorator.getFrame(); @@ -2146,12 +2080,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements window.setLocationRelativeTo(myFrame); } myId2WindowedDecorator.put(info.getId(), myWindowedDecorator); - myWindowedDecorator.addDisposable(new Disposable() { - @Override - public void dispose() { - if (myId2WindowedDecorator.get(info.getId()) != null) { - hideToolWindow(info.getId(), false); - } + myWindowedDecorator.addDisposable(() -> { + if (myId2WindowedDecorator.get(info.getId()) != null) { + hideToolWindow(info.getId(), false); } }); } @@ -2183,7 +2114,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final class RemoveWindowedDecoratorCmd extends FinalizableCommand { private final WindowedDecorator myWindowedDecorator; - private RemoveWindowedDecoratorCmd(final WindowInfoImpl info) { + private RemoveWindowedDecoratorCmd(@NotNull WindowInfoImpl info) { super(myWindowManager.getCommandProcessor()); myWindowedDecorator = getWindowedDecorator(info.getId()); myId2WindowedDecorator.remove(info.getId()); @@ -2255,8 +2186,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final String myId; private final ToolWindowImpl myToolWindow; - - private ToolWindowFocusWatcher(final ToolWindowImpl toolWindow) { + private ToolWindowFocusWatcher(@NotNull ToolWindowImpl toolWindow) { myId = toolWindow.getId(); install(toolWindow.getComponent()); myToolWindow = toolWindow; @@ -2317,27 +2247,27 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements */ private final class MyInternalDecoratorListener implements InternalDecoratorListener { @Override - public void anchorChanged(final InternalDecorator source, final ToolWindowAnchor anchor) { + public void anchorChanged(@NotNull final InternalDecorator source, @NotNull final ToolWindowAnchor anchor) { setToolWindowAnchor(source.getToolWindow().getId(), anchor); } @Override - public void autoHideChanged(final InternalDecorator source, final boolean autoHide) { + public void autoHideChanged(@NotNull final InternalDecorator source, final boolean autoHide) { setToolWindowAutoHide(source.getToolWindow().getId(), autoHide); } @Override - public void hidden(final InternalDecorator source) { + public void hidden(@NotNull final InternalDecorator source) { hideToolWindow(source.getToolWindow().getId(), false); } @Override - public void hiddenSide(final InternalDecorator source) { + public void hiddenSide(@NotNull final InternalDecorator source) { hideToolWindow(source.getToolWindow().getId(), true); } @Override - public void contentUiTypeChanges(InternalDecorator source, @NotNull ToolWindowContentUiType type) { + public void contentUiTypeChanges(@NotNull InternalDecorator source, @NotNull ToolWindowContentUiType type) { setContentUiType(source.getToolWindow().getId(), type); } @@ -2346,13 +2276,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements * tool window depending on decoration type. */ @Override - public void resized(final InternalDecorator source) { + public void resized(@NotNull final InternalDecorator source) { if (!source.isShowing()) { return; // do not recalculate the tool window size if it is not yet shown (and, therefore, has 0,0,0,0 bounds) } final WindowInfoImpl info = getInfo(source.getToolWindow().getId()); - InternalDecorator another = null; if (info.isFloating()) { final Window owner = SwingUtilities.getWindowAncestor(source); if (owner != null) { @@ -2367,6 +2296,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } else { // docked and sliding windows ToolWindowAnchor anchor = info.getAnchor(); + InternalDecorator another = null; if (source.getParent() instanceof Splitter) { float sizeInSplit = anchor.isSplitVertically() ? source.getHeight() : source.getWidth(); Splitter splitter = (Splitter)source.getParent(); @@ -2399,21 +2329,22 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } @Override - public void activated(final InternalDecorator source) { + public void activated(@NotNull final InternalDecorator source) { activateToolWindow(source.getToolWindow().getId(), true, true); } @Override - public void typeChanged(final InternalDecorator source, final ToolWindowType type) { + public void typeChanged(@NotNull final InternalDecorator source, @NotNull final ToolWindowType type) { setToolWindowType(source.getToolWindow().getId(), type); } @Override - public void sideStatusChanged(final InternalDecorator source, final boolean isSideTool) { + public void sideStatusChanged(@NotNull final InternalDecorator source, final boolean isSideTool) { setSideTool(source.getToolWindow().getId(), isSideTool); } - public void visibleStripeButtonChanged(InternalDecorator source, boolean visible) { + @Override + public void visibleStripeButtonChanged(@NotNull InternalDecorator source, boolean visible) { setShowStripeButton(source.getToolWindow().getId(), visible); } } @@ -2546,11 +2477,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return IdeFocusManager.getInstance(myProject).dispatch(e); } + @NotNull public Expirable getTimestamp(boolean trackOnlyForcedCommands) { return IdeFocusManager.getInstance(myProject).getTimestamp(trackOnlyForcedCommands); } - public void setShowStripeButton(String id, boolean visibleOnPanel) { + void setShowStripeButton(@NotNull String id, boolean visibleOnPanel) { checkId(id); WindowInfoImpl info = getInfo(id); if (visibleOnPanel == info.isShowStripeButton()) { @@ -2559,12 +2491,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements info.setShowStripeButton(visibleOnPanel); UsageTrigger.trigger("StripeButton[" + id + "]." + (visibleOnPanel ? "shown" : "hidden")); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); appendApplyWindowInfoCmd(info, commandList); execute(commandList); } - public boolean isShowStripeButton(String id) { + boolean isShowStripeButton(@NotNull String id) { WindowInfoImpl info = getInfo(id); return info == null || info.isShowStripeButton(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java index 2f626df5477e..86a45f418e26 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java @@ -42,10 +42,10 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; +import java.lang.ref.Reference; import java.util.ArrayList; import java.util.Comparator; +import java.util.List; /** * This panel contains all tool stripes and JLayeredPanle at the center area. All tool windows are @@ -59,12 +59,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final IdeFrameImpl myFrame; - private final HashMap myId2Button; - private final HashMap myId2Decorator; - private final HashMap myButton2Info; - private final HashMap myDecorator2Info; - private final HashMap myId2SplitProportion; - private Pair myMaximizedProportion = null; + private final HashMap myId2Button = new HashMap<>(); + private final HashMap myId2Decorator = new HashMap<>(); + private final HashMap myButton2Info = new HashMap<>(); + private final HashMap myDecorator2Info = new HashMap<>(); + private final HashMap myId2SplitProportion = new HashMap<>(); + private Pair myMaximizedProportion; /** * This panel is the layered pane where all sliding tool windows are located. The DEFAULT * layer contains splitters. The PALETTE layer contains all sliding tool windows. @@ -84,29 +84,23 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final Stripe myBottomStripe; private final Stripe myTopStripe; - private final ArrayList myStripes = new ArrayList(); + private final List myStripes = new ArrayList<>(); private final ToolWindowManagerImpl myManager; private boolean myStripesOverlayed; private final Disposable myDisposable = Disposer.newDisposable(); - private boolean myWidescreen = false; - private boolean myLeftHorizontalSplit = false; - private boolean myRightHorizontalSplit = false; + private boolean myWidescreen; + private boolean myLeftHorizontalSplit; + private boolean myRightHorizontalSplit; - ToolWindowsPane(final IdeFrameImpl frame, ToolWindowManagerImpl manager) { + ToolWindowsPane(@NotNull IdeFrameImpl frame, @NotNull ToolWindowManagerImpl manager) { myManager = manager; setOpaque(false); myFrame = frame; - myId2Button = new HashMap(); - myId2Decorator = new HashMap(); - myButton2Info = new HashMap(); - myDecorator2Info = new HashMap(); - myId2SplitProportion = new HashMap(); // Splitters - myVerticalSplitter = new ThreeComponentsSplitter(true); Disposer.register(this, myVerticalSplitter); myVerticalSplitter.setDividerWidth(0); @@ -193,6 +187,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi /** * Invoked when enclosed frame is being shown. */ + @Override public final void addNotify() { super.addNotify(); } @@ -200,6 +195,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi /** * Invoked when enclosed frame is being disposed. */ + @Override public final void removeNotify() { if (ScreenUtil.isStandardAddRemoveNotify(this)) { Disposer.dispose(myDisposable); @@ -211,6 +207,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi return myFrame.getProject(); } + @Override public final void uiSettingsChanged(final UISettings source) { updateToolStripesVisibility(); updateLayout(); @@ -225,10 +222,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * @param comparator which is used to sort buttons within the stripe. * @param finishCallBack invoked when the command is completed. */ + @NotNull final FinalizableCommand createAddButtonCmd(final StripeButton button, - final WindowInfoImpl info, - final Comparator comparator, - final Runnable finishCallBack) { + @NotNull WindowInfoImpl info, + @NotNull Comparator comparator, + @NotNull Runnable finishCallBack) { final WindowInfoImpl copiedInfo = info.copy(); myId2Button.put(copiedInfo.getId(), button); myButton2Info.put(button, copiedInfo); @@ -242,12 +240,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * @param dirtyMode if true then JRootPane will not be validated and repainted after adding * the decorator. Moreover in this (dirty) mode animation doesn't work. */ - final FinalizableCommand createAddDecoratorCmd( - final InternalDecorator decorator, - final WindowInfoImpl info, - final boolean dirtyMode, - final Runnable finishCallBack - ) { + @NotNull + final FinalizableCommand createAddDecoratorCmd(@NotNull InternalDecorator decorator, + @NotNull WindowInfoImpl info, + final boolean dirtyMode, + @NotNull Runnable finishCallBack) { final WindowInfoImpl copiedInfo = info.copy(); final String id = copiedInfo.getId(); @@ -276,10 +273,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * * @param id ID of the button to be removed. */ - final FinalizableCommand createRemoveButtonCmd(final String id, final Runnable finishCallBack) { + @NotNull + final FinalizableCommand createRemoveButtonCmd(@NotNull String id, @NotNull Runnable finishCallBack) { final StripeButton button = getButtonById(id); final WindowInfoImpl info = getButtonInfoById(id); - // + myButton2Info.remove(button); myId2Button.remove(id); return new RemoveToolStripeButtonCmd(button, info, finishCallBack); @@ -291,7 +289,8 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * @param dirtyMode if true then JRootPane will not be validated and repainted after removing * the decorator. Moreover in this (dirty) mode animation doesn't work. */ - final FinalizableCommand createRemoveDecoratorCmd(final String id, final boolean dirtyMode, final Runnable finishCallBack) { + @NotNull + final FinalizableCommand createRemoveDecoratorCmd(@NotNull String id, final boolean dirtyMode, @NotNull Runnable finishCallBack) { final Component decorator = getDecoratorById(id); final WindowInfoImpl info = getDecoratorInfoById(id); @@ -321,14 +320,17 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * * @param component component to be set. */ - final FinalizableCommand createSetEditorComponentCmd(final JComponent component, final Runnable finishCallBack) { + @NotNull + final FinalizableCommand createSetEditorComponentCmd(final JComponent component, @NotNull Runnable finishCallBack) { return new SetEditorComponentCmd(component, finishCallBack); } - final FinalizableCommand createUpdateButtonPositionCmd(String id, final Runnable finishCallback) { + @NotNull + final FinalizableCommand createUpdateButtonPositionCmd(@NotNull String id, @NotNull Runnable finishCallback) { return new UpdateButtonPositionCmd(id, finishCallback); } + @NotNull public final JComponent getMyLayeredPane() { return myLayeredPane; } @@ -361,7 +363,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi /** * Sets (docks) specified component to the specified anchor. */ - private void setComponent(final JComponent component, final ToolWindowAnchor anchor, final float weight) { + private void setComponent(final JComponent component, @NotNull ToolWindowAnchor anchor, final float weight) { if (ToolWindowAnchor.TOP == anchor) { myVerticalSplitter.setFirstComponent(component); myVerticalSplitter.setFirstSize((int)(myLayeredPane.getHeight() * weight)); @@ -383,7 +385,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } } - private JComponent getComponentAt(ToolWindowAnchor anchor) { + private JComponent getComponentAt(@NotNull ToolWindowAnchor anchor) { if (ToolWindowAnchor.TOP == anchor) { return myVerticalSplitter.getFirstComponent(); } @@ -402,12 +404,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } } - private float getPreferredSplitProportion(String id, float defaultValue) { + private float getPreferredSplitProportion(@NotNull String id, float defaultValue) { Float f = myId2SplitProportion.get(id); - return (f == null ? defaultValue : f); + return f == null ? defaultValue : f; } - private WindowInfoImpl getDockedInfoAt(ToolWindowAnchor anchor, boolean side) { + private WindowInfoImpl getDockedInfoAt(@NotNull ToolWindowAnchor anchor, boolean side) { for (WindowInfoImpl info : myDecorator2Info.values()) { if (info.isVisible() && info.isDocked() && info.getAnchor() == anchor && side == info.isSplit()) { return info; @@ -417,7 +419,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi return null; } - public void setDocumentComponent(final JComponent component) { + private void setDocumentComponent(final JComponent component) { (myWidescreen ? myVerticalSplitter : myHorizontalSplitter).setInnerComponent(component); } @@ -464,13 +466,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi if (ToolWindowAnchor.TOP == anchor) { return myTopStripe; } - else if (ToolWindowAnchor.BOTTOM == anchor) { + if (ToolWindowAnchor.BOTTOM == anchor) { return myBottomStripe; } - else if (ToolWindowAnchor.LEFT == anchor) { + if (ToolWindowAnchor.LEFT == anchor) { return myLeftStripe; } - else if (ToolWindowAnchor.RIGHT == anchor) { + if (ToolWindowAnchor.RIGHT == anchor) { return myRightStripe; } @@ -478,7 +480,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } @Nullable - Stripe getStripeFor(final Rectangle screenRec, Stripe preferred) { + Stripe getStripeFor(@NotNull Rectangle screenRec, @NotNull Stripe preferred) { if (preferred.containsScreen(screenRec)) { return myStripes.get(myStripes.indexOf(preferred)); } @@ -504,15 +506,15 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } } - public void stretchWidth(ToolWindow wnd, int value) { + void stretchWidth(@NotNull ToolWindow wnd, int value) { stretch(wnd, value); } - public void stretchHeight(ToolWindow wnd, int value) { + void stretchHeight(@NotNull ToolWindow wnd, int value) { stretch(wnd, value); } - private void stretch(ToolWindow wnd, int value) { + private void stretch(@NotNull ToolWindow wnd, int value) { Pair pair = findResizerAndComponent(wnd); if (pair == null) return; @@ -520,13 +522,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi int actualSize = (vertical ? pair.second.getHeight() : pair.second.getWidth()) + value; boolean first = wnd.getAnchor() == ToolWindowAnchor.LEFT || wnd.getAnchor() == ToolWindowAnchor.TOP; int maxValue = vertical ? myVerticalSplitter.getMaxSize(first) : myHorizontalSplitter.getMaxSize(first); - int minValue = vertical ? myVerticalSplitter.getMinSize(first) : myHorizontalSplitter.getMinSize(first);; + int minValue = vertical ? myVerticalSplitter.getMinSize(first) : myHorizontalSplitter.getMinSize(first); pair.first.setSize(Math.max(minValue, Math.min(maxValue, actualSize))); } @Nullable - private Pair findResizerAndComponent(ToolWindow wnd) { + private Pair findResizerAndComponent(@NotNull ToolWindow wnd) { if (!wnd.isVisible()) return null; Resizer resizer = null; @@ -620,7 +622,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi return myMaximizedProportion != null && myMaximizedProportion.first == wnd; } - public void setMaximized(@NotNull ToolWindow wnd, boolean maximized) { + void setMaximized(@NotNull ToolWindow wnd, boolean maximized) { Pair resizerAndComponent = findResizerAndComponent(wnd); if (resizerAndComponent == null) return; @@ -638,6 +640,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } + @FunctionalInterface interface Resizer { void setSize(int size); @@ -645,25 +648,27 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi abstract class Splitter implements Resizer { ThreeComponentsSplitter mySplitter; - Splitter(ThreeComponentsSplitter splitter) { + Splitter(@NotNull ThreeComponentsSplitter splitter) { mySplitter = splitter; } static class FirstComponent extends Splitter { - FirstComponent(ThreeComponentsSplitter splitter) { + FirstComponent(@NotNull ThreeComponentsSplitter splitter) { super(splitter); } + @Override public void setSize(int size) { mySplitter.setFirstSize(size); } } static class LastComponent extends Splitter { - LastComponent(ThreeComponentsSplitter splitter) { + LastComponent(@NotNull ThreeComponentsSplitter splitter) { super(splitter); } + @Override public void setSize(int size) { mySplitter.setLastSize(size); } @@ -673,10 +678,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi abstract class LayeredPane implements Resizer { Component myComponent; - protected LayeredPane(Component component) { + LayeredPane(@NotNull Component component) { myComponent = component; } + @Override public final void setSize(int size) { _setSize(size); if (myComponent.getParent() instanceof JComponent) { @@ -690,20 +696,22 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi static class Left extends LayeredPane { - Left(Component component) { + Left(@NotNull Component component) { super(component); } + @Override public void _setSize(int size) { myComponent.setSize(size, myComponent.getHeight()); } } static class Right extends LayeredPane { - Right(Component component) { + Right(@NotNull Component component) { super(component); } + @Override public void _setSize(int size) { Rectangle bounds = myComponent.getBounds(); int delta = size - bounds.width; @@ -714,20 +722,22 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } static class Top extends LayeredPane { - Top(Component component) { + Top(@NotNull Component component) { super(component); } + @Override public void _setSize(int size) { myComponent.setSize(myComponent.getWidth(), size); } } static class Bottom extends LayeredPane { - Bottom(Component component) { + Bottom(@NotNull Component component) { super(component); } + @Override public void _setSize(int size) { Rectangle bounds = myComponent.getBounds(); int delta = size - bounds.height; @@ -744,16 +754,17 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - public AddDockedComponentCmd(final JComponent component, - final WindowInfoImpl info, + public AddDockedComponentCmd(@NotNull JComponent component, + @NotNull WindowInfoImpl info, final boolean dirtyMode, - final Runnable finishCallBack) { + @NotNull Runnable finishCallBack) { super(finishCallBack); myComponent = component; myInfo = info; myDirtyMode = dirtyMode; } + @Override public final void run() { try { final ToolWindowAnchor anchor = myInfo.getAnchor(); @@ -774,17 +785,19 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - private AddAndSplitDockedComponentCmd(final JComponent newComponent, - final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack) { + private AddAndSplitDockedComponentCmd(@NotNull JComponent newComponent, + @NotNull WindowInfoImpl info, + final boolean dirtyMode, + @NotNull Runnable finishCallBack) { super(finishCallBack); myNewComponent = newComponent; myInfo = info; myDirtyMode = dirtyMode; } + @Override public void run() { try { - float newWeight; final ToolWindowAnchor anchor = myInfo.getAnchor(); class MySplitter extends Splitter implements UISettingsListener { @Override @@ -801,28 +814,26 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi splitter.setOrientation(anchor.isSplitVertically()); if (!anchor.isHorizontal()) { splitter.setAllowSwitchOrientationByMouseClick(true); - splitter.addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (!Splitter.PROP_ORIENTATION.equals(evt.getPropertyName())) return; - boolean isSplitterHorizontalNow = !splitter.isVertical(); - UISettings settings = UISettings.getInstance(); - if (anchor == ToolWindowAnchor.LEFT) { - if (settings.LEFT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) { - settings.LEFT_HORIZONTAL_SPLIT = isSplitterHorizontalNow; - settings.fireUISettingsChanged(); - } + splitter.addPropertyChangeListener(evt -> { + if (!Splitter.PROP_ORIENTATION.equals(evt.getPropertyName())) return; + boolean isSplitterHorizontalNow = !splitter.isVertical(); + UISettings settings = UISettings.getInstance(); + if (anchor == ToolWindowAnchor.LEFT) { + if (settings.LEFT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) { + settings.LEFT_HORIZONTAL_SPLIT = isSplitterHorizontalNow; + settings.fireUISettingsChanged(); } - if (anchor == ToolWindowAnchor.RIGHT) { - if (settings.RIGHT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) { - settings.RIGHT_HORIZONTAL_SPLIT = isSplitterHorizontalNow; - settings.fireUISettingsChanged(); - } + } + if (anchor == ToolWindowAnchor.RIGHT) { + if (settings.RIGHT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) { + settings.RIGHT_HORIZONTAL_SPLIT = isSplitterHorizontalNow; + settings.fireUISettingsChanged(); } } }); } JComponent c = getComponentAt(anchor); + float newWeight; if (c instanceof InternalDecorator) { InternalDecorator oldComponent = (InternalDecorator)c; if (myInfo.isSplit()) { @@ -872,15 +883,16 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - public AddSlidingComponentCmd(final Component component, - final WindowInfoImpl info, + public AddSlidingComponentCmd(@NotNull Component component, + @NotNull WindowInfoImpl info, final boolean dirtyMode, - final Runnable finishCallBack) { + @NotNull Runnable finishCallBack) { super(finishCallBack); myComponent = component; myInfo = info; myDirtyMode = dirtyMode; } + @Override public final void run() { try { // Show component. @@ -946,15 +958,16 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final Comparator myComparator; public AddToolStripeButtonCmd(final StripeButton button, - final WindowInfoImpl info, - final Comparator comparator, - final Runnable finishCallBack) { + @NotNull WindowInfoImpl info, + @NotNull Comparator comparator, + @NotNull Runnable finishCallBack) { super(finishCallBack); myButton = button; myInfo = info; myComparator = comparator; } + @Override public final void run() { try { final ToolWindowAnchor anchor = myInfo.getAnchor(); @@ -986,12 +999,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final StripeButton myButton; private final WindowInfoImpl myInfo; - public RemoveToolStripeButtonCmd(final StripeButton button, final WindowInfoImpl info, final Runnable finishCallBack) { + public RemoveToolStripeButtonCmd(@NotNull StripeButton button, @NotNull WindowInfoImpl info, @NotNull Runnable finishCallBack) { super(finishCallBack); myButton = button; myInfo = info; } + @Override public final void run() { try { final ToolWindowAnchor anchor = myInfo.getAnchor(); @@ -1023,12 +1037,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - public RemoveDockedComponentCmd(final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack) { + public RemoveDockedComponentCmd(@NotNull WindowInfoImpl info, final boolean dirtyMode, @NotNull Runnable finishCallBack) { super(finishCallBack); myInfo = info; myDirtyMode = dirtyMode; } + @Override public final void run() { try { setComponent(null, myInfo.getAnchor(), 0); @@ -1047,14 +1062,15 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - private RemoveSplitAndDockedComponentCmd(final WindowInfoImpl info, + private RemoveSplitAndDockedComponentCmd(@NotNull WindowInfoImpl info, boolean dirtyMode, - final Runnable finishCallBack) { + @NotNull Runnable finishCallBack) { super(finishCallBack); myInfo = info; myDirtyMode = dirtyMode; } + @Override public void run() { try { ToolWindowAnchor anchor = myInfo.getAnchor(); @@ -1086,12 +1102,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - public RemoveSlidingComponentCmd(Component component, WindowInfoImpl info, boolean dirtyMode, Runnable finishCallBack) { + public RemoveSlidingComponentCmd(Component component, @NotNull WindowInfoImpl info, boolean dirtyMode, @NotNull Runnable finishCallBack) { super(finishCallBack); myComponent = component; myInfo = info; myDirtyMode = dirtyMode; } + @Override public final void run() { try { final UISettings uiSettings = UISettings.getInstance(); @@ -1147,11 +1164,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final class SetEditorComponentCmd extends FinalizableCommand { private final JComponent myComponent; - public SetEditorComponentCmd(final JComponent component, final Runnable finishCallBack) { + public SetEditorComponentCmd(final JComponent component, @NotNull Runnable finishCallBack) { super(finishCallBack); myComponent = component; } + @Override public void run() { try { setDocumentComponent(myComponent); @@ -1167,11 +1185,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final class UpdateButtonPositionCmd extends FinalizableCommand { private final String myId; - private UpdateButtonPositionCmd(String id, final Runnable finishCallBack) { + private UpdateButtonPositionCmd(@NotNull String id, @NotNull Runnable finishCallBack) { super(finishCallBack); myId = id; } + @Override public void run() { try { StripeButton stripeButton = getButtonById(myId); @@ -1209,35 +1228,31 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * These images are used to perform animated showing and hiding of components. * They are the member for performance reason. */ - private SoftReference myBottomImageRef; - private SoftReference myTopImageRef; + private Reference myBottomImageRef; + private Reference myTopImageRef; - public MyLayeredPane(final JComponent splitter) { - myBottomImageRef = new SoftReference(null); - myTopImageRef = new SoftReference(null); + public MyLayeredPane(@NotNull JComponent splitter) { setOpaque(false); add(splitter, JLayeredPane.DEFAULT_LAYER); } - public final Image getBottomImage() { - Pair> result = getImage(myBottomImageRef); + final Image getBottomImage() { + Pair> result = getImage(myBottomImageRef); myBottomImageRef = result.second; return result.first; } - public final Image getTopImage() { - Pair> result = getImage(myTopImageRef); + final Image getTopImage() { + Pair> result = getImage(myTopImageRef); myTopImageRef = result.second; return result.first; } - private Pair> getImage(SoftReference imageRef) { + @NotNull + private Pair> getImage(@Nullable Reference imageRef) { LOG.assertTrue(UISettings.getInstance().ANIMATE_WINDOWS); - BufferedImage image = imageRef.get(); - if ( - image == null || - image.getWidth(null) < getWidth() || image.getHeight(null) < getHeight() - ) { + BufferedImage image = SoftReference.dereference(imageRef); + if (image == null || image.getWidth(null) < getWidth() || image.getHeight(null) < getHeight()) { final int width = Math.max(Math.max(1, getWidth()), myFrame.getWidth()); final int height = Math.max(Math.max(1, getHeight()), myFrame.getHeight()); if (SystemInfo.isWindows) { @@ -1251,7 +1266,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi image = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_RGB); } - imageRef = new SoftReference(image); + imageRef = new SoftReference<>(image); } return Pair.create(image, imageRef); } @@ -1259,6 +1274,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi /** * When component size becomes larger then bottom and top images should be enlarged. */ + @Override public void doLayout() { final int width = getWidth(); final int height = getHeight(); @@ -1295,7 +1311,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } } - public final void setBoundsInPaletteLayer(final Component component, final ToolWindowAnchor anchor, float weight) { + final void setBoundsInPaletteLayer(@NotNull Component component, @NotNull ToolWindowAnchor anchor, float weight) { if (weight < .0f) { weight = WindowInfoImpl.DEFAULT_WEIGHT; } @@ -1322,7 +1338,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } } - public void setStripesOverlayed(boolean stripesOverlayed) { + void setStripesOverlayed(boolean stripesOverlayed) { myStripesOverlayed = stripesOverlayed; updateToolStripesVisibility(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java index 22558914ce43..ff006a1156e2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java @@ -32,16 +32,16 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo /** * XML tag. */ - @NonNls static final String TAG="window_info"; + @NonNls static final String TAG = "window_info"; /** * Default window weight. */ - static final float DEFAULT_WEIGHT= 0.33f; - static final float DEFAULT_SIDE_WEIGHT = 0.5f; + static final float DEFAULT_WEIGHT = 0.33f; + private static final float DEFAULT_SIDE_WEIGHT = 0.5f; private boolean myActive; @NotNull - private ToolWindowAnchor myAnchor; + private ToolWindowAnchor myAnchor = ToolWindowAnchor.LEFT; private boolean myAutoHide; /** * Bounds of window in "floating" mode. It equals to null if @@ -52,9 +52,9 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo private ToolWindowType myInternalType; private ToolWindowType myType; private boolean myVisible; - private boolean myShowStripeButton; - private float myWeight; - private float mySideWeight; + private boolean myShowStripeButton = true; + private float myWeight = DEFAULT_WEIGHT; + private float mySideWeight = DEFAULT_SIDE_WEIGHT; private boolean mySplitMode; @NotNull private ToolWindowContentUiType myContentUiType = ToolWindowContentUiType.TABBED; @@ -62,24 +62,24 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo * Defines order of tool window button inside the stripe. * The default value is -1. */ - private int myOrder; - @NonNls static final String ID_ATTR = "id"; - @NonNls static final String ACTIVE_ATTR = "active"; - @NonNls static final String ANCHOR_ATTR = "anchor"; - @NonNls static final String AUTOHIDE_ATTR = "auto_hide"; - @NonNls static final String INTERNAL_TYPE_ATTR = "internal_type"; - @NonNls static final String TYPE_ATTR = "type"; - @NonNls static final String VISIBLE_ATTR = "visible"; - @NonNls static final String WEIGHT_ATTR = "weight"; - @NonNls static final String SIDE_WEIGHT_ATTR = "sideWeight"; - @NonNls static final String ORDER_ATTR = "order"; - @NonNls static final String X_ATTR = "x"; - @NonNls static final String Y_ATTR = "y"; - @NonNls static final String WIDTH_ATTR = "width"; - @NonNls static final String HEIGHT_ATTR = "height"; - @NonNls static final String SIDE_TOOL_ATTR = "side_tool"; - @NonNls static final String CONTENT_UI_ATTR = "content_ui"; - @NonNls static final String SHOW_STRIPE_BUTTON = "show_stripe_button"; + private int myOrder = -1; + @NonNls private static final String ID_ATTR = "id"; + @NonNls private static final String ACTIVE_ATTR = "active"; + @NonNls private static final String ANCHOR_ATTR = "anchor"; + @NonNls private static final String AUTOHIDE_ATTR = "auto_hide"; + @NonNls private static final String INTERNAL_TYPE_ATTR = "internal_type"; + @NonNls private static final String TYPE_ATTR = "type"; + @NonNls private static final String VISIBLE_ATTR = "visible"; + @NonNls private static final String WEIGHT_ATTR = "weight"; + @NonNls private static final String SIDE_WEIGHT_ATTR = "sideWeight"; + @NonNls private static final String ORDER_ATTR = "order"; + @NonNls private static final String X_ATTR = "x"; + @NonNls private static final String Y_ATTR = "y"; + @NonNls private static final String WIDTH_ATTR = "width"; + @NonNls private static final String HEIGHT_ATTR = "height"; + @NonNls private static final String SIDE_TOOL_ATTR = "side_tool"; + @NonNls private static final String CONTENT_UI_ATTR = "content_ui"; + @NonNls private static final String SHOW_STRIPE_BUTTON = "show_stripe_button"; private boolean myWasRead; @@ -88,18 +88,8 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo * Creates WindowInfo for tool window with specified ID. */ WindowInfoImpl(@NotNull String id) { - myActive = false; - myAnchor = ToolWindowAnchor.LEFT; - myAutoHide = false; - myFloatingBounds = null; myId = id; setType(ToolWindowType.DOCKED); - myVisible = false; - myShowStripeButton = true; - myWeight = DEFAULT_WEIGHT; - mySideWeight = DEFAULT_SIDE_WEIGHT; - myOrder = -1; - mySplitMode = false; } /** @@ -122,7 +112,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo /** * Copies all data from the passed WindowInfo into itself. */ - void copyFrom(final WindowInfoImpl info){ + void copyFrom(@NotNull WindowInfoImpl info){ myActive = info.myActive; myAnchor = info.myAnchor; myAutoHide = info.myAutoHide; @@ -178,15 +168,16 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo * window can be in floating mode, but this method has sense if you want to know what type * tool window had when it was internal one. The method never returns null. */ + @NotNull ToolWindowType getInternalType(){ return myInternalType; } /** * @return current type of tool window. - * @see com.intellij.openapi.wm.ToolWindowType#DOCKED - * @see com.intellij.openapi.wm.ToolWindowType#FLOATING - * @see com.intellij.openapi.wm.ToolWindowType#SLIDING + * @see ToolWindowType#DOCKED + * @see ToolWindowType#FLOATING + * @see ToolWindowType#SLIDING */ @Override public ToolWindowType getType(){ @@ -248,11 +239,12 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo return myVisible; } + @Override public boolean isShowStripeButton() { return myShowStripeButton; } - public void setShowStripeButton(boolean showStripeButton) { + void setShowStripeButton(boolean showStripeButton) { myShowStripeButton = showStripeButton; } @@ -266,7 +258,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo } @Override - @SuppressWarnings({"EmptyCatchBlock"}) + @SuppressWarnings("EmptyCatchBlock") public void readExternal(final Element element) { myId = element.getAttributeValue(ID_ATTR); myWasRead = true; @@ -353,7 +345,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo setTypeAndCheck(type); } //Hardcoded to avoid single-usage-API - private void setTypeAndCheck(ToolWindowType type) { + private void setTypeAndCheck(@NotNull ToolWindowType type) { myType = ToolWindowId.PREVIEW == myId && type == ToolWindowType.DOCKED ? ToolWindowType.SLIDING : type; } @@ -420,7 +412,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo return myAnchor.hashCode()+myId.hashCode()+myType.hashCode()+myOrder; } - @SuppressWarnings({"HardCodedStringLiteral"}) + @SuppressWarnings("HardCodedStringLiteral") public String toString(){ return getClass().getName() + "[myId=" + myId + "; myVisible=" + myVisible @@ -439,7 +431,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo ']'; } - public boolean wasRead() { + boolean wasRead() { return myWasRead; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java index 53e29a1a8749..0d1b997aff80 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java @@ -15,14 +15,11 @@ */ package com.intellij.openapi.wm.impl; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.FrameWrapper; import org.jetbrains.annotations.NotNull; -public final class WindowedDecorator extends FrameWrapper { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.WindowedDecorator"); - +final class WindowedDecorator extends FrameWrapper { private final Project myProject; WindowedDecorator(@NotNull Project project, @NotNull WindowInfoImpl info, @NotNull InternalDecorator internalDecorator) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/FinalizableCommand.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/FinalizableCommand.java index 249391cc253f..b11387bdb1dd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/FinalizableCommand.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/FinalizableCommand.java @@ -17,6 +17,7 @@ package com.intellij.openapi.wm.impl.commands; import com.intellij.openapi.util.Condition; import com.intellij.openapi.wm.ToolWindowManager; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -27,15 +28,15 @@ public abstract class FinalizableCommand implements Runnable{ protected ToolWindowManager myManager; - public FinalizableCommand(final Runnable finishCallBack){ - myFinishCallBack=finishCallBack; + public FinalizableCommand(Runnable finishCallBack){ + myFinishCallBack = finishCallBack; } public final void finish(){ myFinishCallBack.run(); } - public void beforeExecute(final ToolWindowManager toolWindowManager) { + public void beforeExecute(@NotNull ToolWindowManager toolWindowManager) { myManager = toolWindowManager; } diff --git a/platform/testFramework/src/com/intellij/mock/Mock.java b/platform/testFramework/src/com/intellij/mock/Mock.java index d6d960f5bd17..89a0106fff6a 100644 --- a/platform/testFramework/src/com/intellij/mock/Mock.java +++ b/platform/testFramework/src/com/intellij/mock/Mock.java @@ -562,7 +562,7 @@ public class Mock { public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean canCloseContents) { throw new RuntimeException(); } @@ -572,7 +572,7 @@ public class Mock { public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode) { throw new RuntimeException(); } @@ -592,7 +592,7 @@ public class Mock { @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, - final Disposable parentDisposable, final boolean dumbAware) { + @NotNull final Disposable parentDisposable, final boolean dumbAware) { throw new RuntimeException(); } @@ -601,7 +601,7 @@ public class Mock { public ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean secondary) { throw new RuntimeException(); diff --git a/platform/util/src/com/intellij/util/RetinaImage.java b/platform/util/src/com/intellij/util/RetinaImage.java index c9e0eda32c19..590b78241a4d 100644 --- a/platform/util/src/com/intellij/util/RetinaImage.java +++ b/platform/util/src/com/intellij/util/RetinaImage.java @@ -17,6 +17,7 @@ package com.intellij.util; import com.intellij.openapi.util.SystemInfo; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import java.awt.*; import java.awt.image.BufferedImage; @@ -50,6 +51,7 @@ public class RetinaImage { * @param observer the raw image observer * @return the Retina-aware wrapper */ + @NotNull public static Image createFrom(Image image, final int scale, ImageObserver observer) { int w = image.getWidth(observer); int h = image.getHeight(observer); @@ -65,11 +67,13 @@ public class RetinaImage { return hidpi; } + @NotNull public static BufferedImage create(final int width, int height, int type) { return create(null, width, height, type); } + @NotNull private static BufferedImage create(Image image, final int width, int height, int type) { if (SystemInfo.isAppleJvm) { return AppleHiDPIScaledImage.create(width, height, type); diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index a5ef76f881ef..ec24c55d3434 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1779,6 +1779,7 @@ public class UIUtil { } } + @NotNull public static BufferedImage createImage(int width, int height, int type) { if (isRetina()) { return RetinaImage.create(width, height, type); @@ -1787,6 +1788,7 @@ public class UIUtil { return new BufferedImage(width, height, type); } + @NotNull public static BufferedImage createImageForGraphics(Graphics2D g, int width, int height, int type) { if (isRetina(g)) { return RetinaImage.create(width, height, type); From dc423dedc8b749464d8241fe76fdecbbed52b137 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 24 Jun 2016 12:06:29 +0300 Subject: [PATCH 04/36] cancel background VCS initialization on project close start --- .../vcs/impl/ProjectLevelVcsManagerImpl.java | 21 +++++++++++++++---- .../openapi/vcs/impl/VcsInitialization.java | 7 ++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java index b158bf52d26e..fc1252f72e40 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java @@ -33,6 +33,8 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.project.ProjectManagerAdapter; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; @@ -128,24 +130,35 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme private final VcsFileListenerContextHelper myVcsFileListenerContextHelper; private final VcsAnnotationLocalChangesListenerImpl myAnnotationLocalChangesListener; - public ProjectLevelVcsManagerImpl(Project project, final FileStatusManager manager, MessageBus messageBus, - final FileIndexFacade excludedFileIndex) { + public ProjectLevelVcsManagerImpl(Project project, + final FileStatusManager manager, + MessageBus messageBus, + final FileIndexFacade excludedFileIndex, + ProjectManager projectManager, + DefaultVcsRootPolicy defaultVcsRootPolicy, + VcsFileListenerContextHelper vcsFileListenerContextHelper) { myProject = project; myMessageBus = messageBus; mySerialization = new ProjectLevelVcsManagerSerialization(); myOptionsAndConfirmations = new OptionsAndConfirmations(); - myDefaultVcsRootPolicy = DefaultVcsRootPolicy.getInstance(project); + myDefaultVcsRootPolicy = defaultVcsRootPolicy; myInitialization = new VcsInitialization(myProject); Disposer.register(project, myInitialization); // wait for the thread spawned in VcsInitialization to terminate + projectManager.addProjectManagerListener(project, new ProjectManagerAdapter() { + @Override + public void projectClosing(Project project) { + Disposer.dispose(myInitialization); + } + }); myMappings = new NewMappings(myProject, myMessageBus, this, manager); myMappingsToRoots = new MappingsToRoots(myMappings, myProject); myVcsHistoryCache = new VcsHistoryCache(); myContentRevisionCache = new ContentRevisionCache(); myConnect = myMessageBus.connect(); - myVcsFileListenerContextHelper = VcsFileListenerContextHelper.getInstance(myProject); + myVcsFileListenerContextHelper = vcsFileListenerContextHelper; VcsListener vcsListener = new VcsListener() { @Override public void directoryMappingChanged() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java index 83498737c18b..b6ee4ff05886 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java @@ -76,7 +76,7 @@ public class VcsInitialization implements Disposable { } } - public void execute() { + private void execute() { final List> list; synchronized (myLock) { list = myList; @@ -103,6 +103,11 @@ public class VcsInitialization implements Disposable { @Override public void dispose() { myIndicator.cancel(); + cancelBackgroundInitialization(); + } + + private void cancelBackgroundInitialization() { + // do not leave VCS initialization run in background when the project is closed Future future = myFuture; if (future != null) { future.cancel(false); From 1fa4a785b3f37693832c228fd8d75d544ad0230a Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Fri, 24 Jun 2016 12:38:17 +0300 Subject: [PATCH 05/36] EDU-608 "Execute "tests.py" action doesn't create Run Study Tests configuration --- .../coursecreator/run/PyCCRunTestsConfigurationProducer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/run/PyCCRunTestsConfigurationProducer.java b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/run/PyCCRunTestsConfigurationProducer.java index 617345600d30..80f40044bca7 100644 --- a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/run/PyCCRunTestsConfigurationProducer.java +++ b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/run/PyCCRunTestsConfigurationProducer.java @@ -81,7 +81,8 @@ public class PyCCRunTestsConfigurationProducer extends RunConfigurationProducer< String testsPath = taskDir.findChild(EduNames.SRC) != null ? FileUtil.join(taskDirPath, EduNames.SRC, EduNames.TESTS_FILE) : FileUtil.join(taskDirPath, EduNames.TESTS_FILE); - return file.getPath().equals(testsPath) ? testsPath : null; + String filePath = FileUtil.toSystemDependentName(file.getPath()); + return filePath.equals(testsPath) ? testsPath : null; } @Override From 9e9eaac4f1e1d63ed2347e89ebd6621d2db8c87a Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 11:49:44 +0200 Subject: [PATCH 06/36] IDEA-157840 Save Document action doesn't work during indexing --- .../src/com/intellij/ide/actions/SaveDocumentAction.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SaveDocumentAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SaveDocumentAction.java index 5ad331ae5a67..d63683f09f28 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/SaveDocumentAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/SaveDocumentAction.java @@ -1,17 +1,16 @@ package com.intellij.ide.actions; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.DumbAwareAction; /** * @author yole */ -public class SaveDocumentAction extends AnAction { +public class SaveDocumentAction extends DumbAwareAction { @Override public void actionPerformed(AnActionEvent e) { Document doc = getDocument(e); From 7c3cd4327bdbf2eeba47d03c0312bab156b91ca8 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 11:59:44 +0200 Subject: [PATCH 07/36] fail when accessing invalid offsets in completion insert handlers --- .../completion/ConstructorInsertHandler.java | 2 +- .../intellij/codeInsight/completion/OffsetMap.java | 13 +++++++++---- .../completion/CodeCompletionHandlerBase.java | 7 +++---- .../completion/CompletionLookupArranger.java | 8 +++++++- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index 88d14aa13d77..c2ce494ab957 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -58,7 +58,7 @@ public class ConstructorInsertHandler implements InsertHandler= 0 && plEnd >= 0) { diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java b/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java index 90a9b12292e9..8f28dffa0dcb 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java @@ -19,10 +19,10 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -48,10 +48,10 @@ public class OffsetMap implements Disposable { public int getOffset(OffsetKey key) { synchronized (myMap) { final RangeMarker marker = myMap.get(key); - if (marker == null) return -1; + if (marker == null) throw new IllegalArgumentException("Offset " + key + " is not registered"); if (!marker.isValid()) { removeOffset(key); - return -1; + throw new IllegalStateException("Offset " + key + " is invalid: " + marker); } final int endOffset = marker.getEndOffset(); @@ -62,6 +62,11 @@ public class OffsetMap implements Disposable { } } + public boolean containsOffset(OffsetKey key) { + final RangeMarker marker = myMap.get(key); + return marker != null && marker.isValid(); + } + /** * Register key-offset binding. Offset will change together with {@link Document} editing operations * unless an operation replaces completely the offset vicinity. @@ -108,7 +113,7 @@ public class OffsetMap implements Disposable { synchronized (myMap) { ProgressManager.checkCanceled(); assert !myDisposed; - return new ArrayList(myMap.keySet()); + return ContainerUtil.filter(myMap.keySet(), this::containsOffset); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 34a67a149b82..bb8e159880e0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -566,10 +566,9 @@ public class CodeCompletionHandlerBase { final Editor editor = indicator.getEditor(); final int caretOffset = indicator.getCaret().getOffset(); - int idEndOffset = indicator.getIdentifierEndOffset(); - if (idEndOffset < 0) { - idEndOffset = CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset); - } + final int idEndOffset = indicator.getOffsetMap().containsOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET) ? + indicator.getIdentifierEndOffset() : + CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset); final int idEndOffsetDelta = idEndOffset - caretOffset; CompletionAssertions.WatchingInsertionContext context; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java index 1a4be6bf4c56..20a099c0dfb9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java @@ -462,6 +462,10 @@ public class CompletionLookupArranger extends LookupArranger { return; } + if (!context.getOffsetMap().containsOffset(CompletionInitializationContext.START_OFFSET)) { + return; + } + final Document document = context.getDocument(); int startOffset = context.getStartOffset(); int tailOffset = context.getEditor().getCaretModel().getOffset(); @@ -550,7 +554,9 @@ public class CompletionLookupArranger extends LookupArranger { public void addSparedChars(CompletionProgressIndicator indicator, LookupElement item, InsertionContext context, char completionChar) { String textInserted; - if (context.getStartOffset() >= 0 && context.getTailOffset() >= context.getStartOffset()) { + if (context.getOffsetMap().containsOffset(CompletionInitializationContext.START_OFFSET) && + context.getOffsetMap().containsOffset(InsertionContext.TAIL_OFFSET) && + context.getTailOffset() >= context.getStartOffset()) { textInserted = context.getDocument().getImmutableCharSequence().subSequence(context.getStartOffset(), context.getTailOffset()).toString(); } else { textInserted = item.getLookupString(); From f6c3c7be8a5b0d4e2a7bcc634d0b51be146f93d1 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 23 Jun 2016 19:06:09 +0200 Subject: [PATCH 08/36] update CompletionContributor javadoc --- .../codeInsight/completion/CompletionContributor.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java index b6485d6c5432..ac368eae64bd 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java @@ -54,9 +54,7 @@ import java.util.Set; * A: There are two ways. The easier and preferred one is to provide constructor in your contributor and register completion providers there: * {@link #extend(CompletionType, ElementPattern, CompletionProvider)}.
* A more generic way is to override default {@link #fillCompletionVariants(CompletionParameters, CompletionResultSet)} implementation - * and provide your own. It's easier to debug, but harder to write. Remember, that completion variant collection is done in a dedicated thread - * WITHOUT read action, so you'll have to manually invoke {@link com.intellij.openapi.application.Application#runReadAction(Runnable)} each time - * you access PSI. Don't spend long time inside read action, since this will prevent user from selecting lookup element or cancelling completion.

+ * and provide your own. It's easier to debug, but harder to write.

* * Q: What does the {@link CompletionParameters#getPosition()} return?
* A: When completion is invoked, the file being edited is first copied (the original file can be accessed from {@link com.intellij.psi.PsiFile#getOriginalFile()} From 2f92ba525c4e499e31cbab0f4ae3989c40eb7f80 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 12:11:15 +0200 Subject: [PATCH 09/36] O(1) smart pointer removal --- .../SmartPsiElementPointersTest.java | 21 ++- .../SmartPointerManagerImpl.java | 138 +++++++++--------- .../SmartPsiElementPointerImpl.java | 1 + 3 files changed, 86 insertions(+), 74 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java index 37ea37f6c233..b9d84f386d96 100644 --- a/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java @@ -58,10 +58,7 @@ import org.junit.Assert; import java.io.IOException; import java.lang.ref.SoftReference; -import java.util.Collections; -import java.util.List; -import java.util.Random; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; @PlatformTestCase.WrapInCommand @@ -915,4 +912,20 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase { assertEquals(psiClass.getNameIdentifier().getTextRange(), TextRange.create(range)); } + public void testManySmartPointersCreationDeletionPerformance() throws Exception { + String text = StringUtil.repeatSymbol(' ', 100000); + PsiFile file = createFile("a.txt", text); + + PlatformTestUtil.startPerformanceTest("", 2000, () -> { + List pointers = new ArrayList<>(); + for (int i = 0; i < text.length() - 1; i++) { + pointers.add(getPointerManager().createSmartPsiFileRangePointer(file, new TextRange(i, i + 1))); + } + Collections.shuffle(pointers); + for (SmartPsiFileRange pointer : pointers) { + getPointerManager().removePointer(pointer); + } + }).cpuBound().assertTiming(); + } + } diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java index d18fb3ed192c..28a99999203e 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java @@ -29,7 +29,7 @@ import com.intellij.psi.*; import com.intellij.psi.impl.PsiDocumentManagerBase; import com.intellij.psi.util.PsiUtilCore; import com.intellij.reference.SoftReference; -import com.intellij.util.ArrayUtil; +import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -68,7 +68,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager { FilePointersList pointers = reference.file.getUserData(reference.key); if (pointers != null) { - pointers.remove(reference); + pointers.removeReference(reference); } } } @@ -160,12 +160,13 @@ public class SmartPointerManagerImpl extends SmartPointerManager { SmartPointerElementInfo info = pointer.getElementInfo(); if (!(info instanceof SelfElementInfo)) return; + PointerReference reference = new PointerReference(pointer, containingFile, POINTERS_KEY); while (true) { FilePointersList pointers = getPointers(containingFile); if (pointers == null) { pointers = containingFile.putUserDataIfAbsent(POINTERS_KEY, new FilePointersList()); } - if (pointers.add(new PointerReference(pointer, containingFile, ourQueue, POINTERS_KEY))) { + if (pointers.add(reference)) { if (((SelfElementInfo)info).hasRange()) { pointers.markerCache.rangeChanged(); } @@ -193,8 +194,10 @@ public class SmartPointerManagerImpl extends SmartPointerManager { if (containingFile == null) return; VirtualFile vFile = containingFile.getViewProvider().getVirtualFile(); FilePointersList pointers = getPointers(vFile); - if (pointers == null) return; - pointers.remove(pointer); + PointerReference reference = ((SmartPsiElementPointerImpl)pointer).pointerReference; + if (pointers != null && reference != null) { + pointers.removeReference(reference); + } } } @@ -264,17 +267,18 @@ public class SmartPointerManagerImpl extends SmartPointerManager { return myPsiDocManager; } - private static class PointerReference extends WeakReference { + static class PointerReference extends WeakReference { @NotNull private final VirtualFile file; @NotNull private final Key key; + private int index = -2; private PointerReference(@NotNull SmartPsiElementPointerImpl pointer, @NotNull VirtualFile containingFile, - @NotNull ReferenceQueue queue, @NotNull Key key) { - super(pointer, queue); + super(pointer, ourQueue); file = containingFile; this.key = key; + pointer.pointerReference = this; } } @@ -292,104 +296,98 @@ public class SmartPointerManagerImpl extends SmartPointerManager { } if (nextAvailableIndex >= references.length || nextAvailableIndex > size*2) { // overflow or too many dead refs - int newCapacity = nextAvailableIndex >= references.length ? references.length * 3/2 +1 : size * 3/2+1; - PointerReference[] newReferences = new PointerReference[newCapacity]; + int newCapacity = (nextAvailableIndex >= references.length ? references.length : size) * 3 / 2 + 1; + final PointerReference[] newReferences = new PointerReference[newCapacity]; - int o = 0; - for (PointerReference oldRef : references) { - if (SoftReference.dereference(oldRef) != null) { - newReferences[o++] = oldRef; + final int[] o = {0}; + processAlivePointers(new Processor() { + @Override + public boolean process(SmartPsiElementPointerImpl pointer) { + storePointerReference(newReferences, o[0]++, pointer.pointerReference); + return true; } - } + }); references = newReferences; - size = nextAvailableIndex = o; + size = nextAvailableIndex = o[0]; } - references[nextAvailableIndex++] = reference; + assert references[nextAvailableIndex] == null : references[nextAvailableIndex]; + storePointerReference(references, nextAvailableIndex++, reference); size++; mySorted = false; return true; } - private synchronized void remove(@NotNull PointerReference reference) { - int index = ArrayUtil.indexOf(references, reference, 0, nextAvailableIndex); - if (index != -1) { - removeReference(reference, index); - } - } + private synchronized void removeReference(@NotNull PointerReference reference) { + int index = reference.index; + if (index < 0) return; - private synchronized void remove(@NotNull SmartPsiElementPointer smartPointer) { - for (int i = 0; i < nextAvailableIndex; i++) { - PointerReference reference = references[i]; - if (reference != null && reference.get() == smartPointer) { - removeReference(reference, i); - return; - } - } - } - - private void removeReference(@NotNull PointerReference reference, int index) { + assert references[index] == reference : "At " + index + " expected " + reference + ", found " + references[index]; + references[index].index = -1; references[index] = null; if (--size == 0) { reference.file.replace(reference.key, this, null); } } - boolean processAlivePointers(@NotNull Processor processor) { + synchronized boolean processAlivePointers(@NotNull Processor processor) { for (int i = 0; i < nextAvailableIndex; i++) { - SmartPsiElementPointerImpl pointer = SoftReference.dereference(references[i]); - if (pointer != null && !processor.process(pointer)) { + PointerReference ref = references[i]; + if (ref == null) continue; + + SmartPsiElementPointerImpl pointer = ref.get(); + if (pointer == null) { + removeReference(ref); + continue; + } + + if (!processor.process(pointer)) { return false; } } return true; } - synchronized List getSortedInfos() { + private void ensureSorted() { if (!mySorted) { - List hardRefs = ContainerUtil.newArrayListWithCapacity(size); - for (int i = 0; i < nextAvailableIndex; i++) { - PointerReference reference = references[i]; - if (reference == null) continue; + List pointers = new ArrayList(); + processAlivePointers(new CommonProcessors.CollectProcessor(pointers)); + assert size == pointers.size(); - SmartPsiElementPointerImpl pointer = reference.get(); - if (pointer != null) { - hardRefs.add(pointer); - } - else { - removeReference(reference, i); - if (size == 0) { - return Collections.emptyList(); - } - } - } - assert size == hardRefs.size(); - - Arrays.sort(references, 0, nextAvailableIndex, new Comparator() { + Collections.sort(pointers, new Comparator() { @Override - public int compare(PointerReference o1, PointerReference o2) { - SmartPsiElementPointerImpl p1 = SoftReference.dereference(o1); - SmartPsiElementPointerImpl p2 = SoftReference.dereference(o2); - if (p1 == null || p2 == null) { - return p1 != null ? -1 : p2 != null ? 1 : 0; // null references to the end - } + public int compare(SmartPsiElementPointerImpl p1, SmartPsiElementPointerImpl p2) { return MarkerCache.INFO_COMPARATOR.compare((SelfElementInfo)p1.getElementInfo(), (SelfElementInfo)p2.getElementInfo()); } }); - nextAvailableIndex = hardRefs.size(); + + for (int i = 0; i < pointers.size(); i++) { + storePointerReference(references, i, pointers.get(i).pointerReference); + } + Arrays.fill(references, pointers.size(), nextAvailableIndex, null); + nextAvailableIndex = pointers.size(); mySorted = true; } + } - List infos = ContainerUtil.newArrayListWithCapacity(size); - for (int i = 0; i < nextAvailableIndex; i++) { - Reference reference = references[i]; - SmartPsiElementPointerImpl pointer = SoftReference.dereference(reference); - if (pointer != null) { + private static void storePointerReference(PointerReference[] references, int index, PointerReference ref) { + references[index] = ref; + ref.index = index; + } + + synchronized List getSortedInfos() { + ensureSorted(); + + final List infos = ContainerUtil.newArrayListWithCapacity(size); + processAlivePointers(new Processor() { + @Override + public boolean process(SmartPsiElementPointerImpl pointer) { SelfElementInfo info = (SelfElementInfo)pointer.getElementInfo(); - if (!info.hasRange()) break; + if (!info.hasRange()) return false; infos.add(info); + return true; } - } + }); return infos; } diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java index ee7c4c9c249a..01e43e3b8d35 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java @@ -46,6 +46,7 @@ class SmartPsiElementPointerImpl implements SmartPointerEx private final SmartPointerElementInfo myElementInfo; private final Class myElementClass; private byte myReferenceCount = 1; + @Nullable SmartPointerManagerImpl.PointerReference pointerReference; SmartPsiElementPointerImpl(@NotNull Project project, @NotNull E element, @Nullable PsiFile containingFile, boolean forInjected) { this(element, createElementInfo(project, element, containingFile, forInjected), element.getClass()); From aa7feafa829d32856f33fb8b81f98d3f77231ab8 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 24 Jun 2016 12:59:12 +0200 Subject: [PATCH 10/36] simplier / faster duplicates removal / sorting for small fileId array --- .../util/indexing/ValueContainerImpl.java | 8 +-- .../containers/ChangeBufferingList.java | 71 +++++++++++++------ 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java index beda46464af9..8e779cb70315 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java @@ -21,7 +21,6 @@ import com.intellij.util.SmartList; import com.intellij.util.containers.EmptyIterator; import com.intellij.util.indexing.containers.ChangeBufferingList; import com.intellij.util.indexing.containers.IdSet; -import com.intellij.util.indexing.containers.SortedFileIdSetIterator; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.DataInputOutputUtil; import gnu.trove.THashMap; @@ -447,11 +446,8 @@ class ValueContainerImpl extends UpdatableValueContainer implement } else { // serialize positive file ids with delta encoding ChangeBufferingList originalInput = (ChangeBufferingList)fileSetObject; - IntIterator intIterator = originalInput.rawIntIterator(); - if (!intIterator.hasAscendingOrder()) { - // remove possible dupes - intIterator = SortedFileIdSetIterator.getTransientIterator(intIterator); - } + IntIterator intIterator = originalInput.sortedIntIterator(); + if (DebugAssertions.DEBUG) DebugAssertions.assertTrue(intIterator.hasAscendingOrder()); if (intIterator.size() == 1) { DataInputOutputUtil.writeINT(out, intIterator.next()); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/containers/ChangeBufferingList.java b/platform/lang-impl/src/com/intellij/util/indexing/containers/ChangeBufferingList.java index d1a7b6734fdd..57512fb4fd4d 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/containers/ChangeBufferingList.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/containers/ChangeBufferingList.java @@ -19,6 +19,8 @@ import com.intellij.util.indexing.DebugAssertions; import com.intellij.util.indexing.ValueContainer; import gnu.trove.TIntProcedure; +import java.util.Arrays; + import static com.intellij.util.indexing.DebugAssertions.EXTRA_SANITY_CHECKS; /** @@ -122,7 +124,6 @@ public class ChangeBufferingList implements Cloneable { if (randomAccessContainer == null) { int someElementsNumberEstimation = length; - int[] minMax = calcMinMax(changes, length); // todo we can check these lengths instead of only relying upon reaching MAX_FILES //int lengthOfBitSet = IdBitSet.sizeInBytes(minMax[1], minMax[0]); @@ -131,7 +132,7 @@ public class ChangeBufferingList implements Cloneable { if (someElementsNumberEstimation < MAX_FILES) { if (!hasRemovals) { if (mayHaveDupes) { - mergeChangesRemovingDupes(); + removingDupesAndSort(); } idSet = new SortedIdSet(currentChanges, length); @@ -144,7 +145,7 @@ public class ChangeBufferingList implements Cloneable { idSet = new IdBitSet(changes, length, 0); copyChanges = false; } else { - idSet = new IdBitSet(minMax, 0); + idSet = new IdBitSet(calcMinMax(changes, length), 0); } } else if (checkSet != null) { idSet = (RandomAccessIntContainer)randomAccessContainer.clone(); @@ -186,15 +187,40 @@ public class ChangeBufferingList implements Cloneable { } } - private void mergeChangesRemovingDupes() { // duplicated ids can be present for some index due to cancellation of indexing for next index - int[] currentChanges = changes; - ValueContainer.IntIterator sorted = SortedFileIdSetIterator.getTransientIterator(new ChangesIterator(currentChanges, length)); - int lastIndex = 0; - while(sorted.hasNext()) { - currentChanges[lastIndex++] = sorted.next(); - } + private void removingDupesAndSort() { // duplicated ids can be present for some index due to cancellation of indexing for next index + final int[] currentChanges = changes; + final int intLength = length; - length = (short)lastIndex; + if (intLength < 250) { // Plain sorting in Arrays works without allocations for small number of elements (see DualPivotQuicksort.QUICKSORT_THRESHOLD) + Arrays.sort(currentChanges, 0, intLength); + boolean hasDupes = false; + + for(int i = 0, max = intLength - 1; i < max; ++i) { + if (currentChanges[i] == currentChanges[i + 1]) { + hasDupes = true; + break; + } + } + + if (hasDupes) { + int ptr = 0; + for(int i = 1; i < intLength; ++i) { + if (currentChanges[i] != currentChanges[ptr]) { + currentChanges[++ptr] = currentChanges[i]; + } + } + length = (short)(ptr + 1); + } + } else { + ValueContainer.IntIterator sorted = + SortedFileIdSetIterator.getTransientIterator(new ChangesIterator(currentChanges, length, false)); + int lastIndex = 0; + while (sorted.hasNext()) { + currentChanges[lastIndex++] = sorted.next(); + } + + length = (short)lastIndex; + } mayHaveDupes = false; } @@ -262,21 +288,22 @@ public class ChangeBufferingList implements Cloneable { if (currentChanges != null) { if (mayHaveDupes) { synchronized (currentChanges) { - if (mayHaveDupes) mergeChangesRemovingDupes(); + if (mayHaveDupes) removingDupesAndSort(); } } - return new ChangesIterator(currentChanges, length); + return new ChangesIterator(currentChanges, length, true); } } return getRandomAccessContainer().intIterator(); } - public ValueContainer.IntIterator rawIntIterator() { - RandomAccessIntContainer intContainer = randomAccessContainer; - if (intContainer == null && !hasRemovals) { - return new ChangesIterator(changes, length); // dupes are possible + public ValueContainer.IntIterator sortedIntIterator() { + ValueContainer.IntIterator intIterator = intIterator(); + + if (!intIterator.hasAscendingOrder()) { + intIterator = SortedFileIdSetIterator.getTransientIterator(intIterator); } - return getRandomAccessContainer().intIterator(); + return intIterator; } public IdSet getCheckSet() { @@ -287,10 +314,12 @@ public class ChangeBufferingList implements Cloneable { private int cursor; private final int length; private final int[] changes; + private final boolean sorted; - ChangesIterator(int[] _changes, int _length) { + ChangesIterator(int[] _changes, int _length, boolean _sorted) { changes = _changes; length = _length; + sorted = _sorted; } @Override @@ -312,12 +341,12 @@ public class ChangeBufferingList implements Cloneable { @Override public boolean hasAscendingOrder() { - return false; + return sorted; } @Override public ValueContainer.IntIterator createCopyInInitialState() { - return new ChangesIterator(changes, length); + return new ChangesIterator(changes, length, sorted); } } } From 5e380e75266b0caa1b452ca813211cd5579f8aa6 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Thu, 23 Jun 2016 18:03:59 +0300 Subject: [PATCH 11/36] Java inspection: convert the intention for "Remove redundant lambda parameter types" into an INFORMATION-level inspection (IDEA-156028, IDEA-157727) --- ...dundantLambdaParameterTypeInspection.java} | 81 ++++++++----- .../Assignment.java} | 0 .../AssignmentNoParams.java} | 0 .../AssignmentNoTypes.java} | 0 .../Assignment_after.java} | 0 .../AtVarargPlace.java} | 0 .../CallNoTypeArgs.java} | 0 .../CallNoTypeArgs1.java} | 0 .../CallWithTypeArgs.java} | 0 .../CallWithTypeArgs_after.java} | 0 .../redundantLambdaParameterType/InChain.java | 7 ++ .../InChain_after.java | 7 ++ .../InferredFromOtherArgs.java} | 0 .../InferredFromOtherArgs_after.java} | 0 .../NoSelfTypeParam.java} | 0 .../NoSelfTypeParam_after.java} | 0 .../TypeParam.java} | 0 ...ndantLambdaParameterTypeIntentionTest.java | 33 ------ ...dantLambdaParameterTypeInspectionTest.java | 112 ++++++++++++++++++ .../RedundantLambdaParameterType.html | 5 + .../after.java.template | 5 - .../before.java.template | 5 - .../description.html | 5 - resources/src/META-INF/IdeaPlugin.xml | 9 +- 24 files changed, 185 insertions(+), 84 deletions(-) rename java/java-impl/src/com/intellij/{codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntention.java => codeInspection/lambda/RedundantLambdaParameterTypeInspection.java} (73%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignment.java => codeInspection/redundantLambdaParameterType/Assignment.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoParams.java => codeInspection/redundantLambdaParameterType/AssignmentNoParams.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoTypes.java => codeInspection/redundantLambdaParameterType/AssignmentNoTypes.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterAssignment.java => codeInspection/redundantLambdaParameterType/Assignment_after.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAtVarargPlace.java => codeInspection/redundantLambdaParameterType/AtVarargPlace.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs.java => codeInspection/redundantLambdaParameterType/CallNoTypeArgs.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs1.java => codeInspection/redundantLambdaParameterType/CallNoTypeArgs1.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallWithTypeArgs.java => codeInspection/redundantLambdaParameterType/CallWithTypeArgs.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterCallWithTypeArgs.java => codeInspection/redundantLambdaParameterType/CallWithTypeArgs_after.java} (100%) create mode 100644 java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain.java create mode 100644 java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain_after.java rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeInferredFromOtherArgs.java => codeInspection/redundantLambdaParameterType/InferredFromOtherArgs.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterInferredFromOtherArgs.java => codeInspection/redundantLambdaParameterType/InferredFromOtherArgs_after.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeNoSelfTypeParam.java => codeInspection/redundantLambdaParameterType/NoSelfTypeParam.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterNoSelfTypeParam.java => codeInspection/redundantLambdaParameterType/NoSelfTypeParam_after.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeTypeParam.java => codeInspection/redundantLambdaParameterType/TypeParam.java} (100%) delete mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInspection/RedundantLambdaParameterTypeInspectionTest.java create mode 100644 resources-en/src/inspectionDescriptions/RedundantLambdaParameterType.html delete mode 100644 resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/after.java.template delete mode 100644 resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/before.java.template delete mode 100644 resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/description.html diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntention.java b/java/java-impl/src/com/intellij/codeInspection/lambda/RedundantLambdaParameterTypeInspection.java similarity index 73% rename from java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntention.java rename to java/java-impl/src/com/intellij/codeInspection/lambda/RedundantLambdaParameterTypeInspection.java index 38eacc30395a..4e2445fbaee9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntention.java +++ b/java/java-impl/src/com/intellij/codeInspection/lambda/RedundantLambdaParameterTypeInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 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. @@ -13,44 +13,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.codeInsight.daemon.quickFix; +package com.intellij.codeInspection.lambda; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool; +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy; import com.intellij.psi.infos.MethodCandidateInfo; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.util.Function; -import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; /** * User: anna */ -public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntentionAction { - public static final Logger LOG = Logger.getInstance("#" + RedundantLambdaParameterTypeIntention.class.getName()); +public class RedundantLambdaParameterTypeInspection extends BaseJavaBatchLocalInspectionTool { + public static final Logger LOG = Logger.getInstance("#" + RedundantLambdaParameterTypeInspection.class.getName()); @NotNull @Override - public String getFamilyName() { - return "Remove redundant types"; + public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { + return new JavaElementVisitor() { + @Override + public void visitParameterList(PsiParameterList parameterList) { + super.visitParameterList(parameterList); + if (isApplicable(parameterList)) { + holder.registerProblem(parameterList, "Remove redundant types", new LambdaParametersFix()); + } + } + }; } - @NotNull - @Override - public String getText() { - return getFamilyName(); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - final PsiParameterList parameterList = PsiTreeUtil.getParentOfType(element, PsiParameterList.class); - if (parameterList == null) return false; + private static boolean isApplicable(@NotNull PsiParameterList parameterList) { final PsiElement parent = parameterList.getParent(); if (!(parent instanceof PsiLambdaExpression)) return false; final PsiLambdaExpression expression = (PsiLambdaExpression)parent; @@ -73,9 +72,9 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti final PsiTypeParameter[] typeParameters = method.getTypeParameters(); final PsiExpression[] arguments = ((PsiExpressionList)lambdaParent).getExpressions(); - final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project); + final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(parameterList.getProject()); arguments[idx] = javaPsiFacade.getElementFactory().createExpressionFromText( - "(" + StringUtil.join(expression.getParameterList().getParameters(), parameter -> parameter.getName(), ", ") + ") -> {}", expression); + "(" + StringUtil.join(expression.getParameterList().getParameters(), PsiParameter::getName, ", ") + ") -> {}", expression); final PsiParameter[] methodParams = method.getParameterList().getParameters(); final PsiSubstitutor substitutor = javaPsiFacade.getResolveHelper() .inferTypeArguments(typeParameters, methodParams, arguments, ((MethodCandidateInfo)resolveResult).getSiteSubstitutor(), @@ -85,8 +84,7 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti final PsiType psiType = substitutor.substitute(parameter); if (psiType == null || dependsOnTypeParams(psiType, expression, parameter)) return false; } - - + final PsiType paramType; if (idx < methodParams.length) { paramType = methodParams[idx].getType(); @@ -107,12 +105,6 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti return false; } - @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { - final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class); - removeTypes(lambdaExpression); - } - private static void removeTypes(PsiLambdaExpression lambdaExpression) { if (lambdaExpression != null) { final PsiParameter[] parameters = lambdaExpression.getParameterList().getParameters(); @@ -121,7 +113,7 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti text = parameters[0].getName(); } else { - text = "(" + StringUtil.join(parameters, parameter -> parameter.getName(), ", ") + ")"; + text = "(" + StringUtil.join(parameters, PsiParameter::getName, ", ") + ")"; } final PsiLambdaExpression expression = (PsiLambdaExpression)JavaPsiFacade.getElementFactory(lambdaExpression.getProject()) .createExpressionFromText(text + "->{}", lambdaExpression); @@ -135,4 +127,29 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti return LambdaUtil.depends(type, new LambdaUtil.TypeParamsChecker(expr, PsiUtil .resolveGenericsClassInType(LambdaUtil.getFunctionalInterfaceType(expr, false)).getElement()), param2Check); } + + private static class LambdaParametersFix implements LocalQuickFix { + @Nls + @NotNull + @Override + public String getName() { + return getFamilyName(); + } + + @Nls + @NotNull + @Override + public String getFamilyName() { + return "Remove redundant types"; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiElement element = descriptor.getPsiElement(); + final PsiElement parent = element.getParent(); + if (parent instanceof PsiLambdaExpression) { + removeTypes((PsiLambdaExpression)parent); + } + } + } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignment.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/Assignment.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignment.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/Assignment.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoParams.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/AssignmentNoParams.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoParams.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/AssignmentNoParams.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoTypes.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/AssignmentNoTypes.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoTypes.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/AssignmentNoTypes.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterAssignment.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/Assignment_after.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterAssignment.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/Assignment_after.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAtVarargPlace.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/AtVarargPlace.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAtVarargPlace.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/AtVarargPlace.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallNoTypeArgs.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallNoTypeArgs.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs1.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallNoTypeArgs1.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs1.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallNoTypeArgs1.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallWithTypeArgs.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallWithTypeArgs.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallWithTypeArgs.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallWithTypeArgs.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterCallWithTypeArgs.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallWithTypeArgs_after.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterCallWithTypeArgs.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallWithTypeArgs_after.java diff --git a/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain.java new file mode 100644 index 000000000000..7262e3bbca40 --- /dev/null +++ b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain.java @@ -0,0 +1,7 @@ +import java.util.stream.Stream; + +class InChain { + public static void main(String[] args) { + Stream.of("a").map((String s) -> s + "1").forEach(System.out::println); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain_after.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain_after.java new file mode 100644 index 000000000000..857e423db1eb --- /dev/null +++ b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain_after.java @@ -0,0 +1,7 @@ +import java.util.stream.Stream; + +class InChain { + public static void main(String[] args) { + Stream.of("a").map(s -> s + "1").forEach(System.out::println); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeInferredFromOtherArgs.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InferredFromOtherArgs.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeInferredFromOtherArgs.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/InferredFromOtherArgs.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterInferredFromOtherArgs.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InferredFromOtherArgs_after.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterInferredFromOtherArgs.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/InferredFromOtherArgs_after.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeNoSelfTypeParam.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/NoSelfTypeParam.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeNoSelfTypeParam.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/NoSelfTypeParam.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterNoSelfTypeParam.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/NoSelfTypeParam_after.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterNoSelfTypeParam.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/NoSelfTypeParam_after.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeTypeParam.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/TypeParam.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeTypeParam.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/TypeParam.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java deleted file mode 100644 index 4f85962f0a62..000000000000 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2000-2012 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.daemon.quickFix; - -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.testFramework.IdeaTestUtil; - -public class RedundantLambdaParameterTypeIntentionTest extends LightQuickFixParameterizedTestCase { - public void test() throws Exception { doAllTests(); } - - @Override - protected String getBasePath() { - return "/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType"; - } - - @Override - protected Sdk getProjectJDK() { - return IdeaTestUtil.getMockJdk18(); - } -} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantLambdaParameterTypeInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantLambdaParameterTypeInspectionTest.java new file mode 100644 index 000000000000..3e610fcbcf04 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantLambdaParameterTypeInspectionTest.java @@ -0,0 +1,112 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * http:public void testwww() {}.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.codeInspection; + +import com.intellij.JavaTestUtil; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.lambda.RedundantLambdaParameterTypeInspection; +import com.intellij.idea.Bombed; +import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.testFramework.IdeaTestUtil; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; + +import java.util.Calendar; +import java.util.List; + +public class RedundantLambdaParameterTypeInspectionTest extends LightCodeInsightFixtureTestCase { + private RedundantLambdaParameterTypeInspection myInspection = new RedundantLambdaParameterTypeInspection(); + private String myIntentionName = "Remove redundant types"; + + @Override + protected String getBasePath() { + return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInspection/redundantLambdaParameterType"; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + ModuleRootModificationUtil.setModuleSdk(myModule, IdeaTestUtil.getMockJdk18()); + myFixture.enableInspections(myInspection); + } + + @Override + protected void tearDown() throws Exception { + try { + myFixture.disableInspections(myInspection); + } + finally { + super.tearDown(); + } + } + + public void testAssignment() { + doTest(); + } + + public void testAssignmentNoParams() { + assertIntentionNotAvailable(); + } + + public void testAssignmentNoTypes() { + assertIntentionNotAvailable(); + } + + public void testAtVarargPlace() { + assertIntentionNotAvailable(); + } + + public void testCallNoTypeArgs() { + assertIntentionNotAvailable(); + } + + public void testCallNoTypeArgs1() { + assertIntentionNotAvailable(); + } + + public void testCallWithTypeArgs() { + doTest(); + } + + public void testInferredFromOtherArgs() { + doTest(); + } + + public void testNoSelfTypeParam() { + doTest(); + } + + public void testTypeParam() { + assertIntentionNotAvailable(); + } + + @Bombed(month = Calendar.AUGUST, day = 1, user = "Pavel Dolgov") + public void testInChain() { + doTest(); + } + + private void doTest() { + myFixture.configureByFiles(getTestName(false) + ".java"); + final IntentionAction singleIntention = myFixture.findSingleIntention(myIntentionName); + myFixture.launchAction(singleIntention); + myFixture.checkResultByFile(getTestName(false) + ".java", getTestName(false) + "_after.java", true); + } + + private void assertIntentionNotAvailable() { + myFixture.configureByFiles(getTestName(false) + ".java"); + final List intentionActions = myFixture.filterAvailableIntentions(myIntentionName); + assertEmpty(myIntentionName + " is not expected", intentionActions); + } +} \ No newline at end of file diff --git a/resources-en/src/inspectionDescriptions/RedundantLambdaParameterType.html b/resources-en/src/inspectionDescriptions/RedundantLambdaParameterType.html new file mode 100644 index 000000000000..ea49461e2613 --- /dev/null +++ b/resources-en/src/inspectionDescriptions/RedundantLambdaParameterType.html @@ -0,0 +1,5 @@ + + +This inspection removes lambda formal parameter types when they can be inferred from context. + + \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/after.java.template b/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/after.java.template deleted file mode 100644 index 925e26bf3039..000000000000 --- a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/after.java.template +++ /dev/null @@ -1,5 +0,0 @@ -class X { - { - Comparable c = o -> 0; - } -} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/before.java.template b/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/before.java.template deleted file mode 100644 index 84da2abb9213..000000000000 --- a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/before.java.template +++ /dev/null @@ -1,5 +0,0 @@ -class X { - { - Comparable c = (String o) -> 0; - } -} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/description.html b/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/description.html deleted file mode 100644 index 7e47e9314b11..000000000000 --- a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/description.html +++ /dev/null @@ -1,5 +0,0 @@ - - -This intention removes lambda formal parameter types when they can be inferred from context. - - \ No newline at end of file diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 29201b0565b2..4be169a82fed 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -800,11 +800,12 @@ groupKey="group.names.declaration.redundancy" enabledByDefault="true" level="WARNING" implementationClass="com.intellij.codeInspection.SimplifyStreamApiCallChainsInspection" displayName="Simplify stream API call chains"/> + - - com.intellij.codeInsight.daemon.quickFix.RedundantLambdaParameterTypeIntention - Java/Declaration - com.intellij.codeInsight.intention.impl.SplitIfAction Java/Control Flow From 92838f48bcf6d205ea12c667bb01e9205e2c3735 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Fri, 24 Jun 2016 13:59:42 +0300 Subject: [PATCH 12/36] Java inspection: Get rid of RemoveRedundantElseAction, as it's totally inferior to DataFlowInspection (IDEA-157727) --- .../quickfix/RemoveRedundantElseAction.java | 109 ------------------ .../quickFix/removeRedundantElse/after1.java | 13 --- .../quickFix/removeRedundantElse/before1.java | 14 --- .../beforeCanThrowException.java | 15 --- .../beforeIfElseChain.java | 17 --- .../RemoveRedundantElseActionTest.java | 32 ----- .../after.java.template | 8 -- .../before.java.template | 10 -- .../description.html | 7 -- resources/src/META-INF/IdeaPlugin.xml | 4 - 10 files changed, 229 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantElseAction.java delete mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/after1.java delete mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/before1.java delete mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeCanThrowException.java delete mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeIfElseChain.java delete mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java delete mode 100644 resources-en/src/intentionDescriptions/RemoveRedundantElseAction/after.java.template delete mode 100644 resources-en/src/intentionDescriptions/RemoveRedundantElseAction/before.java.template delete mode 100644 resources-en/src/intentionDescriptions/RemoveRedundantElseAction/description.html diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantElseAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantElseAction.java deleted file mode 100644 index 28db235e1e1b..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantElseAction.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2000-2009 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.daemon.impl.quickfix; - -import com.intellij.codeInsight.FileModificationService; -import com.intellij.codeInsight.daemon.QuickFixBundle; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.*; -import com.intellij.psi.controlFlow.*; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.BitUtil; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @author ven - */ -public class RemoveRedundantElseAction extends PsiElementBaseIntentionAction { - private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.RemoveRedundantElseAction"); - - @Override - @NotNull - public String getText() { - return QuickFixBundle.message("remove.redundant.else.fix"); - } - - @Override - @NotNull - public String getFamilyName() { - return QuickFixBundle.message("remove.redundant.else.fix"); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - if (element instanceof PsiKeyword && - element.getParent() instanceof PsiIfStatement && - PsiKeyword.ELSE.equals(element.getText())) { - PsiIfStatement ifStatement = (PsiIfStatement)element.getParent(); - if (ifStatement.getElseBranch() == null) return false; - PsiStatement thenBranch = ifStatement.getThenBranch(); - if (thenBranch == null) return false; - PsiElement block = PsiTreeUtil.getParentOfType(ifStatement, PsiCodeBlock.class); - if (block != null) { - while (cantCompleteNormally(thenBranch, block)) { - thenBranch = getPrevThenBranch(thenBranch); - if (thenBranch == null) return true; - } - return false; - } - } - return false; - } - - @Nullable - private static PsiStatement getPrevThenBranch(@NotNull PsiElement thenBranch) { - final PsiElement ifStatement = thenBranch.getParent(); - final PsiElement parent = ifStatement.getParent(); - if (parent instanceof PsiIfStatement && ((PsiIfStatement)parent).getElseBranch() == ifStatement) { - return ((PsiIfStatement)parent).getThenBranch(); - } - return null; - } - - private static boolean cantCompleteNormally(@NotNull PsiStatement thenBranch, PsiElement block) { - try { - ControlFlow controlFlow = ControlFlowFactory.getInstance(thenBranch.getProject()).getControlFlow(block, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance()); - int startOffset = controlFlow.getStartOffset(thenBranch); - int endOffset = controlFlow.getEndOffset(thenBranch); - return startOffset != -1 && endOffset != -1 && !BitUtil.isSet(ControlFlowUtil.getCompletionReasons(controlFlow, startOffset, endOffset), ControlFlowUtil.NORMAL_COMPLETION_REASON); - } - catch (AnalysisCanceledException e) { - return false; - } - } - - @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { - if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; - PsiIfStatement ifStatement = (PsiIfStatement)element.getParent(); - LOG.assertTrue(ifStatement != null && ifStatement.getElseBranch() != null); - PsiStatement elseBranch = ifStatement.getElseBranch(); - if (elseBranch instanceof PsiBlockStatement) { - PsiElement[] statements = ((PsiBlockStatement)elseBranch).getCodeBlock().getStatements(); - if (statements.length > 0) { - ifStatement.getParent().addRangeAfter(statements[0], statements[statements.length-1], ifStatement); - } - } else { - ifStatement.getParent().addAfter(elseBranch, ifStatement); - } - ifStatement.getElseBranch().delete(); - } -} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/after1.java deleted file mode 100644 index d0d55761f11b..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/after1.java +++ /dev/null @@ -1,13 +0,0 @@ -// "Remove redundant 'else'" "true" -class a { - void foo() { - int a = 0; - int b = 0; - if (a != b) { - return; - } - a = b; - a++; - } -} - diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/before1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/before1.java deleted file mode 100644 index ea4609835464..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/before1.java +++ /dev/null @@ -1,14 +0,0 @@ -// "Remove redundant 'else'" "true" -class a { - void foo() { - int a = 0; - int b = 0; - if (a != b) { - return; - } else { - a = b; - } - a++; - } -} - diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeCanThrowException.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeCanThrowException.java deleted file mode 100644 index 8fd59ef094f3..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeCanThrowException.java +++ /dev/null @@ -1,15 +0,0 @@ -// "Remove redundant 'else'" "false" -import java.io.IOException; -class a { - void foo(boolean condition) throws IOException{ - if (condition) { - tMethod(); - } - else { - System.out.println("else"); - } - } - - void tMethod() throws IOException {} -} - diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeIfElseChain.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeIfElseChain.java deleted file mode 100644 index f702178d781f..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeIfElseChain.java +++ /dev/null @@ -1,17 +0,0 @@ -// "Remove redundant 'else'" "false" -class a { - void foo() { - int a = 0; - int b = 0; - if (a != b) { - a = 10; - } else if (a + 1 == b) { - return; - } - else { - a = b; - } - a++; - } -} - diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java deleted file mode 100644 index 0a33ada748f8..000000000000 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2000-2010 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.daemon.quickFix; - -/** - * User: anna - * Date: Aug 30, 2010 - */ -public class RemoveRedundantElseActionTest extends LightQuickFixParameterizedTestCase { - - public void test() throws Exception { doAllTests(); } - - @Override - protected String getBasePath() { - return "/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse"; - } - -} - diff --git a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/after.java.template b/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/after.java.template deleted file mode 100644 index 6bbd9d56135a..000000000000 --- a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/after.java.template +++ /dev/null @@ -1,8 +0,0 @@ -public class X { - void f(int i) { - if (i==0) { - return; - } - int j = 0; - } -} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/before.java.template b/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/before.java.template deleted file mode 100644 index edad99d14f45..000000000000 --- a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/before.java.template +++ /dev/null @@ -1,10 +0,0 @@ -public class X { - void f(int i) { - if (i==0) { - return; - } - else { - int j = 0; - } - } -} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/description.html b/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/description.html deleted file mode 100644 index 8992a7b29b2c..000000000000 --- a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/description.html +++ /dev/null @@ -1,7 +0,0 @@ - - -This intention detaches else clause from the if statement, -if corresponding then clause never completes normally. - - - diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 4be169a82fed..ca43d4c44eda 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -826,10 +826,6 @@ com.intellij.codeInsight.intention.impl.ExtractIfConditionAction Java/Control Flow - - com.intellij.codeInsight.daemon.impl.quickfix.RemoveRedundantElseAction - Java/Control Flow - com.intellij.codeInsight.intention.impl.AddNotNullAnnotationIntention Java/Annotations From 9a9cfcdbfa6ce71f3ad391df01447588a864fe43 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Tue, 21 Jun 2016 13:03:06 +0300 Subject: [PATCH 13/36] Cannot do keyboard input in debug mode with interactive console turned on (PY-16825 ) In debug console we should handle input calls on Python side and notify Java side, like we do it in Interactive Python Console. After handling input we should send it back to Python process. --- .../_pydev_bundle/pydev_console_utils.py | 25 ++++++++ .../pydev/_pydevd_bundle/pydevd_comm.py | 9 +++ python/helpers/pydev/pydevd.py | 8 +++ .../python/debugger/IPyDebugProcess.java | 2 + .../debugger/pydev/AbstractCommand.java | 5 ++ .../python/debugger/pydev/RemoteDebugger.java | 3 + .../python/console/PythonConsoleView.java | 9 +++ .../PythonDebugConsoleCommunication.java | 57 +++++++++++++------ .../python/debugger/PyDebugProcess.java | 7 +++ 9 files changed, 109 insertions(+), 16 deletions(-) diff --git a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py index 19be9971bda1..112d0ae36de9 100644 --- a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py +++ b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py @@ -114,6 +114,31 @@ class StdIn(BaseStdIn): return '\n' +#======================================================================================================================= +# DebugConsoleStdIn +#======================================================================================================================= +class DebugConsoleStdIn(BaseStdIn): + ''' + Object to be added to stdin (to emulate it as non-blocking while the next line arrives) + ''' + + def __init__(self, dbg, original_stdin): + BaseStdIn.__init__(self) + self.debugger = dbg + self.original_stdin = original_stdin + + def readline(self, *args, **kwargs): + # Notify Java side about input and call original function + try: + cmd = self.debugger.cmd_factory.make_input_requested_message() + self.debugger.writer.add_command(cmd) + return self.original_stdin.readline(*args, **kwargs) + except Exception: + import traceback + traceback.print_exc() + return '\n' + + class CodeFragment: def __init__(self, text, is_single_line=True): self.text = text diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py index babdc3571d0a..ec0c13d692b5 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py @@ -138,6 +138,7 @@ CMD_GET_ARRAY = 143 CMD_STEP_INTO_MY_CODE = 144 CMD_GET_CONCURRENCY_EVENT = 145 CMD_SHOW_RETURN_VALUES = 146 +CMD_INPUT_REQUESTED = 147 CMD_VERSION = 501 CMD_RETURN = 502 @@ -191,6 +192,7 @@ ID_TO_MEANING = { '144': 'CMD_STEP_INTO_MY_CODE', '145': 'CMD_GET_CONCURRENCY_EVENT', '146': 'CMD_SHOW_RETURN_VALUES', + '147': 'CMD_INPUT_REQUESTED', '501': 'CMD_VERSION', '502': 'CMD_RETURN', @@ -779,6 +781,13 @@ class NetCommandFactory: except: return self.make_error_message(0, get_exception_traceback_str()) + def make_input_requested_message(self): + try: + return NetCommand(CMD_INPUT_REQUESTED, 0, '') + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_exit_message(self): try: net = NetCommand(CMD_EXIT, 0, '') diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index b27daef92c57..e333f90df1c7 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -1180,6 +1180,7 @@ def _locked_settrace( if bufferStdErrToServer: init_stderr_redirect() + patch_stdin(debugger) debugger.set_trace_for_frame_and_parents(get_frame(), False, overwrite_prev_trace=overwrite_prev_trace) @@ -1382,6 +1383,12 @@ def apply_debugger_options(setup_options): enable_qt_support() +def patch_stdin(debugger): + from _pydev_bundle.pydev_console_utils import DebugConsoleStdIn + orig_stdin = sys.stdin + sys.stdin = DebugConsoleStdIn(debugger, orig_stdin) + + #======================================================================================================================= # main #======================================================================================================================= @@ -1512,6 +1519,7 @@ if __name__ == '__main__': pass # It's ok not having stackless there... is_module = setup['module'] + patch_stdin(debugger) if fix_app_engine_debug: sys.stderr.write("pydev debugger: google app engine integration enabled\n") diff --git a/python/pydevSrc/com/jetbrains/python/debugger/IPyDebugProcess.java b/python/pydevSrc/com/jetbrains/python/debugger/IPyDebugProcess.java index 82155bacd88f..ce55d8e87e83 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/IPyDebugProcess.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/IPyDebugProcess.java @@ -37,5 +37,7 @@ public interface IPyDebugProcess extends PyFrameAccessor { boolean isSuspendedOnAllThreadsPolicy(); + void consoleInputRequested(); + XDebugSession getSession(); } diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java index 4ed466cacbc6..941e39343ba4 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java @@ -50,6 +50,7 @@ public abstract class AbstractCommand { public static final int STEP_INTO_MY_CODE = 144; public static final int LOG_CONCURRENCY_EVENT = 145; public static final int SHOW_RETURN_VALUES = 146; + public static final int INPUT_REQUESTED = 147; public static final int ERROR = 901; @@ -197,6 +198,10 @@ public abstract class AbstractCommand { return command == WRITE_TO_CONSOLE; } + public static boolean isInputRequested(final int command) { + return command == INPUT_REQUESTED; + } + public static boolean isExitEvent(final int command) { return command == EXIT; } diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java index 7b15821aef8b..08b93e8fbfa1 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java @@ -547,6 +547,9 @@ public class RemoteDebugger implements ProcessDebugger { else if (AbstractCommand.isConcurrencyEvent(frame.getCommand())) { recordConcurrencyEvent(ProtocolParser.parseConcurrencyEvent(frame.getPayload(), myDebugProcess.getPositionConverter())); } + else if (AbstractCommand.isInputRequested(frame.getCommand())) { + myDebugProcess.consoleInputRequested(); + } else { placeResponse(frame.getSequence(), frame); } diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java index e3e17b295f02..d6f4f63f0834 100644 --- a/python/src/com/jetbrains/python/console/PythonConsoleView.java +++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java @@ -95,6 +95,15 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable myExecuteActionHandler = consoleExecuteActionHandler; } + public void inputRequested() { + final ConsoleCommunication consoleCommunication = myExecuteActionHandler.getConsoleCommunication(); + if (consoleCommunication instanceof PythonDebugConsoleCommunication) { + ((PythonDebugConsoleCommunication)consoleCommunication).waitingForInput = true; + myExecuteActionHandler.inputRequested(); + myExecuteActionHandler.setEnabled(true); + } + } + @Override public void requestFocus() { IdeFocusManager.findInstance().requestFocus(getConsoleEditor().getContentComponent(), true); diff --git a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java index 25eb30cc0552..e357c4dd89ab 100644 --- a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java @@ -15,8 +15,10 @@ */ package com.jetbrains.python.console; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.encoding.EncodingProjectManager; import com.intellij.util.Function; import com.jetbrains.python.console.pydev.AbstractConsoleCommunication; import com.jetbrains.python.console.pydev.InterpreterResponse; @@ -26,12 +28,16 @@ import com.jetbrains.python.debugger.PyDebuggerException; import com.jetbrains.python.debugger.pydev.PyDebugCallback; import org.jetbrains.annotations.NotNull; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; import java.util.List; /** * @author traff */ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunication { + private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.console.pydev.PythonDebugConsoleCommunication"); private final PyDebugProcess myDebugProcess; private final StringBuilder myExpression = new StringBuilder(); @@ -55,7 +61,7 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio @Override public boolean isWaitingForInput() { - return false; + return waitingForInput; } @Override @@ -78,24 +84,43 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio } public void execInterpreter(ConsoleCodeFragment code, final Function callback) { - myExpression.append(code.getText()); - exec(new ConsoleCodeFragment(myExpression.toString(), false), new PyDebugCallback>() { - @Override - public void ok(Pair executed) { - boolean more = executed.second; - - if (!more) { - myExpression.setLength(0); + if (waitingForInput) { + final OutputStream processInput = myDebugProcess.getProcessHandler().getProcessInput(); + if (processInput != null) { + try { + final Charset defaultCharset = EncodingProjectManager.getInstance(myDebugProcess.getProject()).getDefaultCharset(); + String text = code.getText(); + // we save previous command text!!! + processInput.write((text + "\n").getBytes(defaultCharset)); + processInput.flush(); + } + catch (IOException e) { + LOG.error(e.getMessage()); } - callback.fun(new InterpreterResponse(more, isWaitingForInput())); } + waitingForInput = false; + } + else { - @Override - public void error(PyDebuggerException exception) { - myExpression.setLength(0); - callback.fun(new InterpreterResponse(false, isWaitingForInput())); - } - }); + myExpression.append(code.getText()); + exec(new ConsoleCodeFragment(myExpression.toString(), false), new PyDebugCallback>() { + @Override + public void ok(Pair executed) { + boolean more = executed.second; + + if (!more) { + myExpression.setLength(0); + } + callback.fun(new InterpreterResponse(more, isWaitingForInput())); + } + + @Override + public void error(PyDebuggerException exception) { + myExpression.setLength(0); + callback.fun(new InterpreterResponse(false, isWaitingForInput())); + } + }); + } } @Override diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java index ea7c3afccd9c..3ab7886b6237 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java @@ -346,6 +346,13 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr } } + @Override + public void consoleInputRequested() { + if (myExecutionConsole instanceof PythonDebugLanguageConsoleView) { + ((PythonDebugLanguageConsoleView)myExecutionConsole).getPydevConsoleView().inputRequested(); + } + } + protected void afterConnect() { } From d3f57ad6cbdd0d9f1e03bcd357eb7a0123cb4d8c Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Tue, 21 Jun 2016 13:58:29 +0300 Subject: [PATCH 14/36] Input doesn't work in Debug Console (PY-19853) Clear input buffer before waiting for input --- .../python/console/PydevConsoleExecuteActionHandler.java | 4 ++++ .../src/com/jetbrains/python/console/PythonConsoleView.java | 1 + 2 files changed, 5 insertions(+) diff --git a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java index 4f1b10b78692..67f52844bfe9 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java @@ -100,6 +100,10 @@ public class PydevConsoleExecuteActionHandler extends ProcessBackedConsoleExecut sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), false)); } + public void clearInputBuffer() { + myInputBuffer = null; + } + private void processOneLine(String line) { int indentSize = IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false); line = StringUtil.trimTrailing(line); diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java index d6f4f63f0834..32b4dc981093 100644 --- a/python/src/com/jetbrains/python/console/PythonConsoleView.java +++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java @@ -101,6 +101,7 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable ((PythonDebugConsoleCommunication)consoleCommunication).waitingForInput = true; myExecuteActionHandler.inputRequested(); myExecuteActionHandler.setEnabled(true); + myExecuteActionHandler.clearInputBuffer(); } } From d0960c95eb238da5e886fba1ca978cfacb6f996b Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Wed, 22 Jun 2016 12:55:14 +0300 Subject: [PATCH 15/36] Fixes after review --- python/helpers/pydev/_pydev_bundle/pydev_console_utils.py | 2 +- .../python/console/PythonDebugConsoleCommunication.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py index 112d0ae36de9..c9078e14457d 100644 --- a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py +++ b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py @@ -132,11 +132,11 @@ class DebugConsoleStdIn(BaseStdIn): try: cmd = self.debugger.cmd_factory.make_input_requested_message() self.debugger.writer.add_command(cmd) - return self.original_stdin.readline(*args, **kwargs) except Exception: import traceback traceback.print_exc() return '\n' + return self.original_stdin.readline(*args, **kwargs) class CodeFragment: diff --git a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java index e357c4dd89ab..ccf185786ece 100644 --- a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java @@ -89,9 +89,7 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio if (processInput != null) { try { final Charset defaultCharset = EncodingProjectManager.getInstance(myDebugProcess.getProject()).getDefaultCharset(); - String text = code.getText(); - // we save previous command text!!! - processInput.write((text + "\n").getBytes(defaultCharset)); + processInput.write((code.getText() + "\n").getBytes(defaultCharset)); processInput.flush(); } catch (IOException e) { From 6adafab3647db23e1d2526190f4a580c3fe9a629 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Wed, 22 Jun 2016 12:55:55 +0300 Subject: [PATCH 16/36] We shouldn't add new line character here --- .../python/console/PythonDebugConsoleCommunication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java index ccf185786ece..78ecbf99578b 100644 --- a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java @@ -89,7 +89,7 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio if (processInput != null) { try { final Charset defaultCharset = EncodingProjectManager.getInstance(myDebugProcess.getProject()).getDefaultCharset(); - processInput.write((code.getText() + "\n").getBytes(defaultCharset)); + processInput.write((code.getText()).getBytes(defaultCharset)); processInput.flush(); } catch (IOException e) { From f27aae5d8817448e404f18f57a3326174fbbdef0 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Fri, 24 Jun 2016 14:15:31 +0300 Subject: [PATCH 17/36] EDU-537 Empty task text with opened task files --- .../jetbrains/edu/learning/StudyBasePluginConfigurator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java index 99163eea7916..35ecc643f5bf 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java @@ -56,6 +56,11 @@ public abstract class StudyBasePluginConfigurator implements StudyPluginConfigur @Override public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) { + for (VirtualFile openedFile : source.getOpenFiles()) { + if (StudyUtils.getTaskFile(project, openedFile) != null) { + return; + } + } toolWindow.setEmptyText(project); } From 76df9978039e5e8eeaf9d7faf00fcabe45eb4c54 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 24 Jun 2016 14:06:36 +0300 Subject: [PATCH 18/36] EDU-644 Main toolwindow: hint for navigation between placeholders is lost --- .../src/com/jetbrains/edu/learning/StudyProjectComponent.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java index cfb8faa2bbb0..5a505d0bb7f3 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java @@ -26,6 +26,8 @@ import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.util.containers.hash.HashMap; import com.jetbrains.edu.learning.actions.StudyActionWithShortcut; +import com.jetbrains.edu.learning.actions.StudyNextWindowAction; +import com.jetbrains.edu.learning.actions.StudyPrevWindowAction; import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.core.EduUtils; import com.jetbrains.edu.learning.courseFormat.Course; @@ -113,6 +115,8 @@ public class StudyProjectComponent implements ProjectComponent { } } } + addShortcut(StudyNextWindowAction.ACTION_ID, new String[]{StudyNextWindowAction.SHORTCUT, StudyNextWindowAction.SHORTCUT2}); + addShortcut(StudyPrevWindowAction.ACTION_ID, new String[]{StudyPrevWindowAction.SHORTCUT}); } else { LOG.warn("Actions on toolbar are nulls"); From ba2c8bedea62e71f3cd751f9bd3ef71dd1f0c348 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Fri, 24 Jun 2016 15:00:17 +0300 Subject: [PATCH 19/36] EDU-322 Next Task: unnecessary jumping from Project Root to actual task position in a tree --- .../actions/StudyTaskNavigationAction.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java index 363e73e37018..efc81bc33be7 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java @@ -8,7 +8,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.util.ui.tree.TreeUtil; import com.jetbrains.edu.learning.StudyState; import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.core.EduNames; @@ -44,9 +43,6 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut int nextTaskIndex = nextTask.getIndex(); int lessonIndex = nextTask.getLesson().getIndex(); Map nextTaskFiles = nextTask.getTaskFiles(); - if (nextTaskFiles.isEmpty()) { - return; - } VirtualFile projectDir = project.getBaseDir(); String lessonDirName = EduNames.LESSON + String.valueOf(lessonIndex); if (projectDir == null) { @@ -61,15 +57,26 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut if (taskDir == null) { return; } + if (nextTaskFiles.isEmpty()) { + ProjectView.getInstance(project).select(taskDir, taskDir, false); + return; + } VirtualFile shouldBeActive = getFileToActivate(project, nextTaskFiles, taskDir); JTree tree = ProjectView.getInstance(project).getCurrentProjectViewPane().getTree(); - TreePath path = TreeUtil.getFirstNodePath(tree); - tree.collapsePath(path); + TreePath path = tree.getSelectionPath(); + if (path != null) { + TreePath oldSelectionPath = path.getParentPath(); + if (oldSelectionPath != null) { + tree.collapsePath(oldSelectionPath); + tree.fireTreeCollapsed(oldSelectionPath); + } + } if (shouldBeActive != null) { ProjectView.getInstance(project).select(shouldBeActive, shouldBeActive, false); FileEditorManager.getInstance(project).openFile(shouldBeActive, true); } + ToolWindow runToolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.RUN); if (runToolWindow != null) { runToolWindow.hide(null); @@ -82,7 +89,7 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut for (Map.Entry entry : nextTaskFiles.entrySet()) { String name = entry.getKey(); TaskFile taskFile = entry.getValue(); - VirtualFile srcDir = taskDir.findChild("src"); + VirtualFile srcDir = taskDir.findChild(EduNames.SRC); VirtualFile vf = srcDir == null ? taskDir.findChild(name) : srcDir.findChild(name); if (vf != null) { FileEditorManager.getInstance(project).openFile(vf, true); From 343aa6cab9ee3bc67c511db206045fdfef882bc8 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Fri, 24 Jun 2016 15:08:11 +0300 Subject: [PATCH 20/36] EDU-536 Open task file with placeholders when new task opened --- .../edu/learning/actions/StudyTaskNavigationAction.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java index efc81bc33be7..97495aad8f0d 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java @@ -92,8 +92,10 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut VirtualFile srcDir = taskDir.findChild(EduNames.SRC); VirtualFile vf = srcDir == null ? taskDir.findChild(name) : srcDir.findChild(name); if (vf != null) { - FileEditorManager.getInstance(project).openFile(vf, true); - if (!taskFile.getAnswerPlaceholders().isEmpty()) { + if (shouldBeActive != null) { + FileEditorManager.getInstance(project).openFile(vf, true); + } + if (shouldBeActive == null && !taskFile.getAnswerPlaceholders().isEmpty()) { shouldBeActive = vf; } } From b16891ee2d7fd221c270368eb3b36c20870f0677 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 21 Jun 2016 12:28:25 +0300 Subject: [PATCH 21/36] [vcs]: refactor NewEditChangelist panel to be able provide more complex component for names; * provide inner wrapper for future usages; * style: use DocumentAdapter; * cleanup; --- .../changes/ui/NewEditChangelistPanel.java | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java index e9a1fa117556..c3f502c3e0c9 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java @@ -17,8 +17,8 @@ package com.intellij.openapi.vcs.changes.ui; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider; +import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; @@ -30,19 +30,20 @@ import com.intellij.ui.*; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; import java.util.Set; public abstract class NewEditChangelistPanel extends JPanel { - private EditorTextField myNameTextField; - private EditorTextField myDescriptionTextArea; - private JPanel myAdditionalControlsPanel; - private JCheckBox myMakeActiveCheckBox; + private final EditorTextField myNameTextField; + private final EditorTextField myDescriptionTextArea; + private final JPanel myAdditionalControlsPanel; + private final JCheckBox myMakeActiveCheckBox; private Consumer myConsumer; - private final Project myProject; + protected final Project myProject; public NewEditChangelistPanel(final Project project) { super(new GridBagLayout()); @@ -52,14 +53,15 @@ public abstract class NewEditChangelistPanel extends JPanel { final JLabel nameLabel = new JLabel(VcsBundle.message("edit.changelist.name")); add(nameLabel, gb); - ++ gb.gridx; + ++gb.gridx; gb.fill = GridBagConstraints.HORIZONTAL; gb.weightx = 1; - myNameTextField = createEditorField(project, 1); + ComponentWithTextFieldWrapper componentWithTextField = createComponentWithTextField(project); + myNameTextField = componentWithTextField.getEditorTextField(); myNameTextField.setOneLineMode(true); myNameTextField.setText("New changelist"); myNameTextField.selectAll(); - add(myNameTextField, gb); + add(componentWithTextField.myComponent, gb); nameLabel.setLabelFor(myNameTextField); ++ gb.gridy; @@ -100,11 +102,7 @@ public abstract class NewEditChangelistPanel extends JPanel { support.installSearch(myNameTextField, myDescriptionTextArea); myConsumer = support.addControls(myAdditionalControlsPanel, initial); } - myNameTextField.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void beforeDocumentChange(DocumentEvent event) { - } - + myNameTextField.getDocument().addDocumentListener(new DocumentAdapter() { @Override public void documentChanged(DocumentEvent event) { nameChangedImpl(myProject, initial); @@ -160,6 +158,17 @@ public abstract class NewEditChangelistPanel extends JPanel { protected abstract void nameChanged(String errorMessage); + protected ComponentWithTextFieldWrapper createComponentWithTextField(Project project) { + final EditorTextField editorTextField = createEditorField(project, 1); + return new ComponentWithTextFieldWrapper(editorTextField) { + @NotNull + @Override + public EditorTextField getEditorTextField() { + return editorTextField; + } + }; + } + private static EditorTextField createEditorField(final Project project, final int defaultLines) { final EditorTextFieldProvider service = ServiceManager.getService(project, EditorTextFieldProvider.class); final EditorTextField editorField; @@ -178,4 +187,15 @@ public abstract class NewEditChangelistPanel extends JPanel { editorField.getComponent().setMinimumSize(new Dimension(100, (int)(height * 1.3))); return editorField; } + + protected abstract static class ComponentWithTextFieldWrapper { + @NotNull private final Component myComponent; + + public ComponentWithTextFieldWrapper(@NotNull Component component) { + myComponent = component; + } + + @NotNull + abstract EditorTextField getEditorTextField(); + } } From 873214c889caf37a003a16ad08d006e041e80b16 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 21 Jun 2016 12:59:32 +0300 Subject: [PATCH 22/36] [vcs]: change ui/ux for ChangeListChooser (IDEA-153163, IDEA-150818) * get rid of radio button, use editable combobox instead; * update description if exist; * change combobox model from local changelist to string; remove linkRenderer bacause links are not clickable anyway; --- .../changes/ui/ChangeListChooserPanel.form | 50 ---- .../changes/ui/ChangeListChooserPanel.java | 220 ++++++++---------- 2 files changed, 103 insertions(+), 167 deletions(-) delete mode 100644 platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.form diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.form b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.form deleted file mode 100644 index 7228db028df1..000000000000 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.form +++ /dev/null @@ -1,50 +0,0 @@ - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index 363d5f1e319f..11b9be18052e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -15,161 +15,144 @@ */ package com.intellij.openapi.vcs.changes.ui; +import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.VcsConfiguration; import com.intellij.openapi.vcs.changes.ChangeList; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.LocalChangeList; import com.intellij.openapi.vcs.changes.committed.CommittedChangeListRenderer; -import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkRenderer; -import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.*; import com.intellij.util.NullableConsumer; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.util.*; +import java.util.Collection; +import java.util.Collections; import java.util.List; -/** - * @author yole - */ public class ChangeListChooserPanel extends JPanel { - private static final Comparator CHANGE_LIST_COMPARATOR = new Comparator() { - @Override - public int compare(ChangeList o1, ChangeList o2) { - return o1.getName().compareToIgnoreCase(o2.getName()); - } - }; - private JPanel myPanel; - private JRadioButton myRbExisting; - private JRadioButton myRbNew; - private JComboBox myExistingListsCombo; - private NewEditChangelistPanel myNewListPanel; + private final MyEditorComboBox myExistingListsCombo; + private final NewEditChangelistPanel myListPanel; private final NullableConsumer myOkEnabledListener; - private Project myProject; + private final Project myProject; public ChangeListChooserPanel(final Project project, @NotNull final NullableConsumer okEnabledListener) { super(new BorderLayout()); myProject = project; - myOkEnabledListener = okEnabledListener; - add(myPanel, BorderLayout.CENTER); - - myRbExisting.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - updateEnabledItems(); - } - }); - } - - public void init() { - myExistingListsCombo.setRenderer(new ColoredListCellRendererWrapper() { - private final IssueLinkRenderer myLinkRenderer = new IssueLinkRenderer(myProject, this); - + myExistingListsCombo = new MyEditorComboBox(project); + myExistingListsCombo.setEditable(true); + myExistingListsCombo.setRenderer(new ColoredListCellRenderer() { @Override - protected void doCustomize(JList list, Object value, int index, boolean selected, boolean hasFocus) { - if (value instanceof LocalChangeList) { - String name = ((LocalChangeList) value).getName(); - - if (myExistingListsCombo.getWidth() == 0) { + protected void customizeCellRenderer(@NotNull JList list, + String value, + int index, + boolean selected, + boolean hasFocus) { + if (value != null) { + String name = value; + LocalChangeList changeList = ChangeListManager.getInstance(myProject).findChangeList(name); + int visibleWidth = myExistingListsCombo.getEditorTextField().getVisibleRect().width; + if (visibleWidth == 0) { name = name.length() > 10 ? name.substring(0, 7) + " .." : name; } else { final FontMetrics fm = list.getFontMetrics(list.getFont()); final int width = fm.stringWidth(name); - final int listWidth = myExistingListsCombo.getWidth(); - if ((listWidth > 0) && (width > listWidth)) { - final String truncated = CommittedChangeListRenderer.truncateDescription(name, fm, listWidth - fm.stringWidth(" ..") - 7); + if ((visibleWidth > 0) && (width > visibleWidth)) { + final String truncated = CommittedChangeListRenderer + .truncateDescription(name, fm, visibleWidth - fm.stringWidth(" ..") - 7); if (truncated.length() > 5) { name = truncated + " .."; } } } - myLinkRenderer.appendTextWithLinks(name, ((LocalChangeList)value).isDefault() - ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES); + append(name, changeList != null && changeList.isDefault() + ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES + : SimpleTextAttributes.REGULAR_ATTRIBUTES); } } }); - myNewListPanel.init(null); - myRbNew.addFocusListener(new FocusAdapter() { + myListPanel = new NewEditChangelistPanel(myProject) { + @Override - public void focusGained(FocusEvent e) { - if (myRbNew.isSelected()) { - IdeFocusManager.getInstance(myProject).requestFocus(myNewListPanel.getPreferredFocusedComponent(), true); - } + protected NewEditChangelistPanel.ComponentWithTextFieldWrapper createComponentWithTextField(Project project) { + return new ComponentWithTextFieldWrapper(myExistingListsCombo) { + @NotNull + @Override + public EditorTextField getEditorTextField() { + return myExistingListsCombo.getEditorTextField(); + } + }; } - }); - final ComboboxSpeedSearch search = new ComboboxSpeedSearch(myExistingListsCombo); - search.setComparator(new SpeedSearchComparator(true, false)); + + @Override + protected void nameChanged(String errorMessage) { + LocalChangeList list = getExistingChangelist(); + setDescription(list != null ? list.getComment() : ""); + myOkEnabledListener.consume(errorMessage); + } + + @Override + protected void nameChangedImpl(Project project, LocalChangeList initial) { + nameChanged(StringUtil.isEmptyOrSpaces(getChangeListName()) ? "Cannot create new changelist with empty name." : null); + } + }; + myOkEnabledListener = okEnabledListener; + add(myListPanel, BorderLayout.CENTER); + } + + public void init() { + myListPanel.init(null); } public void setChangeLists(Collection changeLists) { - List list = new ArrayList(changeLists); - Collections.sort(list, CHANGE_LIST_COMPARATOR); - myExistingListsCombo.setModel(new CollectionComboBoxModel(list, null)); + List changelistNames = ContainerUtil.map(changeLists, ChangeList::getName); + Collections.sort(changelistNames); + myExistingListsCombo.setModel(new CollectionComboBoxModel(changelistNames)); } public void setDefaultName(String name) { - if (! StringUtil.isEmptyOrSpaces(name)) { - myNewListPanel.setChangeListName(name); + if (!StringUtil.isEmptyOrSpaces(name)) { + myListPanel.setChangeListName(name); } } private void updateEnabledItems() { - if (myRbExisting.isSelected()) { - myExistingListsCombo.setEnabled(true); - UIUtil.setEnabled(myNewListPanel, false, true); - myExistingListsCombo.requestFocus(); - } - else { - myExistingListsCombo.setEnabled(false); - UIUtil.setEnabled(myNewListPanel, true, true); - myNewListPanel.requestFocus(); - } if (myProject != null) { - myNewListPanel.nameChangedImpl(myProject, null); + myListPanel.nameChangedImpl(myProject, null); } } + /** + * Method used as getResult, usually invoked inside doOkAction + */ @Nullable public LocalChangeList getSelectedList(Project project) { ChangeListManager manager = ChangeListManager.getInstance(project); - if (myRbNew.isSelected()) { - String newText = myNewListPanel.getChangeListName(); - if (manager.findChangeList(newText) != null) { - Messages.showErrorDialog(project, - VcsBundle.message("changes.newchangelist.warning.already.exists.text", newText), - VcsBundle.message("changes.newchangelist.warning.already.exists.title")); - return null; - } - } - final boolean existingSelected = myRbExisting.isSelected(); - VcsConfiguration.getInstance(myProject).PRESELECT_EXISTING_CHANGELIST = existingSelected; + String changeListName = myListPanel.getChangeListName(); + LocalChangeList localChangeList = manager.findChangeList(changeListName); - if (existingSelected) { - return (LocalChangeList)myExistingListsCombo.getSelectedItem(); + if (localChangeList == null) { + localChangeList = manager.addChangeList(changeListName, myListPanel.getDescription()); + myListPanel.changelistCreatedOrChanged(localChangeList); } else { - LocalChangeList changeList = manager.addChangeList(myNewListPanel.getChangeListName(), myNewListPanel.getDescription()); - myNewListPanel.changelistCreatedOrChanged(changeList); - if (myNewListPanel.getMakeActiveCheckBox().isSelected()) { - manager.setDefaultChangeList(changeList); - } - VcsConfiguration.getInstance(project).MAKE_NEW_CHANGELIST_ACTIVE = myNewListPanel.getMakeActiveCheckBox().isSelected(); - - return changeList; + //update description if changed + localChangeList.setComment(myListPanel.getDescription()); } + if (myListPanel.getMakeActiveCheckBox().isSelected()) { + manager.setDefaultChangeList(localChangeList); + } + VcsConfiguration.getInstance(project).MAKE_NEW_CHANGELIST_ACTIVE = myListPanel.getMakeActiveCheckBox().isSelected(); + return localChangeList; } public void setDefaultSelection(final ChangeList defaultSelection) { @@ -177,34 +160,37 @@ public class ChangeListChooserPanel extends JPanel { myExistingListsCombo.setSelectedIndex(0); } else { - myExistingListsCombo.setSelectedItem(defaultSelection); + myExistingListsCombo.setSelectedItem(defaultSelection.getName()); } - //if defaultSelection was predefined as null then it means we could not use existing is this context - if (defaultSelection != null && VcsConfiguration.getInstance(myProject).PRESELECT_EXISTING_CHANGELIST) { - myRbExisting.setSelected(true); - } - else { - myRbNew.setSelected(true); - } - + updateDescription(); updateEnabledItems(); } - public JComponent getPreferredFocusedComponent() { - return myRbExisting.isSelected() ? myExistingListsCombo : myNewListPanel.getPreferredFocusedComponent(); + private void updateDescription() { + LocalChangeList list = getExistingChangelist(); + myListPanel.setDescription(list != null ? list.getComment() : ""); } - private void createUIComponents() { - myNewListPanel = new NewEditChangelistPanel(myProject) { + private LocalChangeList getExistingChangelist() { + ChangeListManager manager = ChangeListManager.getInstance(myProject); + String changeListName = myListPanel.getChangeListName(); + return manager.findChangeList(changeListName); + } - @Override - protected void nameChanged(String errorMessage) { - if (myRbExisting.isSelected()) { - myOkEnabledListener.consume(null); - } else { - myOkEnabledListener.consume(errorMessage); - } - } - }; + public JComponent getPreferredFocusedComponent() { + return myExistingListsCombo; + } + + private static class MyEditorComboBox extends ComboBox { + + public MyEditorComboBox(Project project) { + super(); + setEditor(new StringComboboxEditor(project, FileTypes.PLAIN_TEXT, this)); + } + + @NotNull + private EditorTextField getEditorTextField() { + return ObjectUtils.assertNotNull((EditorTextField)getEditor().getEditorComponent()); + } } } From 8900f469e1ca86a6935b8924a54d95c28d174d0a Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 21 Jun 2016 13:45:53 +0300 Subject: [PATCH 23/36] [vcs]: provide full completion for move to another changelist panel including combobox model and tasks from task plugin --- .../completion/ComboEditorCompletionContributor.java | 7 ++++++- .../vcs/changes/ui/ChangeListChooserPanel.java | 11 ++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java index 59159a84a440..0246e779a10a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.Key; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.ui.StringComboboxEditor; @@ -30,6 +31,8 @@ import javax.swing.*; */ public class ComboEditorCompletionContributor extends CompletionContributor{ + public static final Key CONTINUE_RUN_COMPLETION = Key.create("CONTINUE_RUN_COMPLETION"); + @Override public void fillCompletionVariants(@NotNull final CompletionParameters parameters, @NotNull final CompletionResultSet result) { if (parameters.getInvocationCount() == 0) { @@ -60,7 +63,9 @@ public class ComboEditorCompletionContributor extends CompletionContributor{ }), count-i)); } } - result.stopHere(); + if (!Boolean.TRUE.equals(document.getUserData(CONTINUE_RUN_COMPLETION))) { + result.stopHere(); + } } } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index 11b9be18052e..bf679b26b99c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.vcs.changes.ui; +import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; @@ -37,6 +38,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import static com.intellij.codeInsight.completion.ComboEditorCompletionContributor.CONTINUE_RUN_COMPLETION; + public class ChangeListChooserPanel extends JPanel { private final MyEditorComboBox myExistingListsCombo; @@ -185,7 +188,13 @@ public class ChangeListChooserPanel extends JPanel { public MyEditorComboBox(Project project) { super(); - setEditor(new StringComboboxEditor(project, FileTypes.PLAIN_TEXT, this)); + setEditor(new StringComboboxEditor(project, FileTypes.PLAIN_TEXT, this) { + @Override + protected void onEditorCreate(EditorEx editor) { + super.onEditorCreate(editor); + getDocument().putUserData(CONTINUE_RUN_COMPLETION, true); + } + }); } @NotNull From 55da3bcd9a0acb9cf9e7d61c5de15d5522869e9a Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 21 Jun 2016 17:29:21 +0300 Subject: [PATCH 24/36] [vcs]: support undo * without invokeLater undo changelist name may lead to unable undo action for description: error message will be shown; --- .../openapi/vcs/changes/ui/ChangeListChooserPanel.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index bf679b26b99c..842e79e66848 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -15,6 +15,8 @@ */ package com.intellij.openapi.vcs.changes.ui; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; @@ -29,6 +31,7 @@ import com.intellij.ui.*; import com.intellij.util.NullableConsumer; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -97,9 +100,10 @@ public class ChangeListChooserPanel extends JPanel { } @Override + @CalledInAwt protected void nameChanged(String errorMessage) { - LocalChangeList list = getExistingChangelist(); - setDescription(list != null ? list.getComment() : ""); + //invoke later because of undo manager problem: when you try to undo changelist after description was already changed manually + ApplicationManager.getApplication().invokeLater(() -> updateDescription(), ModalityState.current()); myOkEnabledListener.consume(errorMessage); } From e9bcb80a3938dc5598279545ad5e6e09ebf9102c Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Fri, 17 Jun 2016 15:27:37 +0300 Subject: [PATCH 25/36] [vcs]: IDEA-154192 improve ok action enabled status for Unshelve Changes dialog; cleanUp; --- .../patch/ApplyPatchDifferentiatedDialog.java | 17 ++++++++++++----- .../vcs/changes/ui/ChangeListChooserPanel.java | 4 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java index 3a4f74e753e6..6d234ea67fd7 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java @@ -60,7 +60,6 @@ import com.intellij.ui.*; import com.intellij.util.Alarm; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.Convertor; import com.intellij.util.containers.MultiMap; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; @@ -196,7 +195,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myReset = myCanChangePatchFile ? this::reset : EmptyRunnable.getInstance(); myChangeListChooser = new ChangeListChooserPanel(project, errorMessage -> { - setOKActionEnabled(errorMessage == null); + setOKActionEnabled(errorMessage == null && isChangeTreeEnabled()); setErrorText(errorMessage); }); ChangeListManager changeListManager = ChangeListManager.getInstance(project); @@ -244,7 +243,15 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } private void updateOkActions() { - setOKActionEnabled(!myChangesTreeList.getIncludedChanges().isEmpty()); + boolean changeTreeEnabled = isChangeTreeEnabled(); + setOKActionEnabled(changeTreeEnabled); + if (changeTreeEnabled) { + myChangeListChooser.updateEnabled(); + } + } + + private boolean isChangeTreeEnabled() { + return !myChangesTreeList.getIncludedChanges().isEmpty(); } private void queueRequest() { @@ -371,6 +378,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myReader = patchReader; updateTree(true); paintBusy(false); + updateOkActions(); }, ModalityState.stateForComponent(myCenterPanel)); } } @@ -519,8 +527,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { protected DefaultTreeModel buildTreeModel(List changes, ChangeNodeDecorator changeNodeDecorator) { TreeModelBuilder builder = new TreeModelBuilder(myProject, isShowFlatten()); - return builder.buildModel(ObjectsConvertor.convert(changes, - (Convertor)o -> o), changeNodeDecorator); + return builder.buildModel(ObjectsConvertor.convert(changes, o -> o), changeNodeDecorator); } @Override diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index 842e79e66848..7d4a4c21d50e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -132,7 +132,7 @@ public class ChangeListChooserPanel extends JPanel { } } - private void updateEnabledItems() { + public void updateEnabled() { if (myProject != null) { myListPanel.nameChangedImpl(myProject, null); } @@ -170,7 +170,7 @@ public class ChangeListChooserPanel extends JPanel { myExistingListsCombo.setSelectedItem(defaultSelection.getName()); } updateDescription(); - updateEnabledItems(); + updateEnabled(); } private void updateDescription() { From 193e9df1b225d3e3f39edb7fa9fefb468323a912 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 22 Jun 2016 12:28:53 +0300 Subject: [PATCH 26/36] [completion]: make editorComboBox completion for String ComboBoxes available during dumb mode --- .../completion/ComboEditorCompletionContributor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java index 0246e779a10a..10994f07e85b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -29,7 +30,7 @@ import javax.swing.*; /** * @author peter */ -public class ComboEditorCompletionContributor extends CompletionContributor{ +public class ComboEditorCompletionContributor extends CompletionContributor implements DumbAware { public static final Key CONTINUE_RUN_COMPLETION = Key.create("CONTINUE_RUN_COMPLETION"); From 619176bba75d528485fbe62ee746573a093cf087 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Thu, 23 Jun 2016 17:01:13 +0300 Subject: [PATCH 27/36] [vcs]: use last typed description for new changelist instead of empty one --- .../changes/ui/ChangeListChooserPanel.java | 22 ++++++++++++++++++- .../changes/ui/NewEditChangelistPanel.java | 4 ++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index 7d4a4c21d50e..1c93f351669a 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -37,6 +37,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -49,6 +51,7 @@ public class ChangeListChooserPanel extends JPanel { private final NewEditChangelistPanel myListPanel; private final NullableConsumer myOkEnabledListener; private final Project myProject; + private String myLastTypedDescription; public ChangeListChooserPanel(final Project project, @NotNull final NullableConsumer okEnabledListener) { super(new BorderLayout()); @@ -107,6 +110,20 @@ public class ChangeListChooserPanel extends JPanel { myOkEnabledListener.consume(errorMessage); } + @Override + public void init(LocalChangeList initial) { + super.init(initial); + myDescriptionTextArea.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + super.focusLost(e); + if (getExistingChangelist() == null) { + myLastTypedDescription = myListPanel.getDescription(); + } + } + }); + } + @Override protected void nameChangedImpl(Project project, LocalChangeList initial) { nameChanged(StringUtil.isEmptyOrSpaces(getChangeListName()) ? "Cannot create new changelist with empty name." : null); @@ -175,7 +192,10 @@ public class ChangeListChooserPanel extends JPanel { private void updateDescription() { LocalChangeList list = getExistingChangelist(); - myListPanel.setDescription(list != null ? list.getComment() : ""); + String newText = list != null ? list.getComment() : myLastTypedDescription; + if (!StringUtil.equals(myListPanel.getDescription(), newText)) { + myListPanel.setDescription(newText); + } } private LocalChangeList getExistingChangelist() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java index c3f502c3e0c9..98260d3f6a08 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java @@ -37,8 +37,8 @@ import java.awt.*; import java.util.Set; public abstract class NewEditChangelistPanel extends JPanel { - private final EditorTextField myNameTextField; - private final EditorTextField myDescriptionTextArea; + protected final EditorTextField myNameTextField; + protected final EditorTextField myDescriptionTextArea; private final JPanel myAdditionalControlsPanel; private final JCheckBox myMakeActiveCheckBox; From 3d1ce692151a3b4758d6a3bff828ee3637997d31 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 24 Jun 2016 14:54:48 +0300 Subject: [PATCH 28/36] brought back error label listener --- .../python/newProject/actions/ProjectSpecificSettingsStep.java | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java index 1bdc5359402e..6952315028b8 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java @@ -139,6 +139,7 @@ public class ProjectSpecificSettingsStep extends ProjectSettingsStepBase impleme super.initGeneratorListeners(); if (myProjectGenerator instanceof PythonProjectGenerator) { ((PythonProjectGenerator)myProjectGenerator).addSettingsStateListener(this::checkValid); + myErrorLabel.addMouseListener(((PythonProjectGenerator)myProjectGenerator).getErrorLabelMouseListener()); } } From bb7d889d9c1921e391eeddae12da4c19fca48552 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 24 Jun 2016 15:17:56 +0300 Subject: [PATCH 29/36] EDU-621, EDU-623 Disable PEP8 new line warning for python tasks Disable "too long line" from PEP8 by default --- .../edu/PyCharmEduInitialConfigurator.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/python/educational-python/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java b/python/educational-python/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java index 49d301b1c327..d479b31c6893 100644 --- a/python/educational-python/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java +++ b/python/educational-python/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java @@ -56,10 +56,15 @@ import com.intellij.openapi.project.ProjectManagerAdapter; import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.*; import com.intellij.platform.DirectoryProjectConfigurator; import com.intellij.platform.PlatformProjectViewOpener; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiManager; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.ui.treeStructure.Tree; @@ -68,6 +73,7 @@ import com.intellij.util.messages.MessageBus; import com.intellij.util.ui.tree.TreeUtil; import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.codeInsight.PyCodeInsightSettings; +import com.jetbrains.python.inspections.PyPep8Inspection; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -77,6 +83,7 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -201,7 +208,11 @@ public class PyCharmEduInitialConfigurator { @Override public void run() { if (project.isDisposed()) return; + updateInspectionsProfile(); + openProjectStructure(); + } + private void openProjectStructure() { ToolWindowManager.getInstance(project).invokeLater(new Runnable() { int count = 0; @@ -212,12 +223,24 @@ public class PyCharmEduInitialConfigurator { return; } ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("Project"); - if (toolWindow !=null && toolWindow.getType() != ToolWindowType.SLIDING) { + if (toolWindow != null && toolWindow.getType() != ToolWindowType.SLIDING) { toolWindow.activate(null); } } }); } + + private void updateInspectionsProfile() { + final String[] codes = new String[]{"W29", "E501"}; + final VirtualFile baseDir = project.getBaseDir(); + final PsiDirectory directory = PsiManager.getInstance(project).findDirectory(baseDir); + if (directory != null) { + InspectionProjectProfileManager.getInstance(project).getInspectionProfile().modifyToolSettings( + Key.create(PyPep8Inspection.INSPECTION_SHORT_NAME), directory, + inspection -> Collections.addAll(inspection.ignoredErrors, codes) + ); + } + } }); } }); From 951cdba7658d3a14469a4b93a6c771215002d2fe Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 24 Jun 2016 14:43:04 +0300 Subject: [PATCH 30/36] revert optimization: parameter types are compared for language level < 1.8 --- .../impl/source/tree/java/PsiMethodCallExpressionImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java index 50b49e3b29b1..18ed26bd5e43 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java @@ -237,9 +237,7 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements PsiType ret, JavaResolveResult result, LanguageLevel languageLevel) { - PsiSubstitutor substitutor = result instanceof MethodCandidateInfo && !PsiPolyExpressionUtil.isMethodCallTypeDependsOnInference(call, method) - ? ((MethodCandidateInfo)result).getSiteSubstitutor() - : result.getSubstitutor(); + PsiSubstitutor substitutor = result.getSubstitutor(); PsiType substitutedReturnType = substitutor.substitute(ret); if (substitutedReturnType == null) { return TypeConversionUtil.erasure(ret); From 3ee8b6d1e86cf888f3379e332811adae1a47189c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 24 Jun 2016 15:31:03 +0300 Subject: [PATCH 31/36] unrelated defaults: correct type if super classes come from different jdks (both 1.8 but of different versions) --- .../intellij/psi/util/PsiSuperMethodUtil.java | 37 ++++++++++++++++++- .../com/intellij/psi/impl/TypeCorrector.java | 32 ++-------------- .../codeInsight/multipleJdks/java7/p/I.java | 4 ++ ...latedDefaultsFromDifferentJdkVersions.java | 3 ++ .../codeInsight/multipleJdks/java8/p/I.java | 4 ++ ...latedDefaultsFromDifferentJdkVersions.java | 8 ++++ .../MultipleJdksHighlightingTest.java | 12 +++++- 7 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java index 2148bd45b3cb..641cb6e7ee88 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java @@ -15,11 +15,15 @@ */ package com.intellij.psi.util; +import com.intellij.openapi.roots.FileIndexFacade; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.containers.HashSet; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.LinkedHashSet; import java.util.List; @@ -111,6 +115,7 @@ public class PsiSuperMethodUtil { public static Map> collectOverrideEquivalents(@NotNull PsiClass aClass) { final Map> overrideEquivalent = new THashMap>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY); + final GlobalSearchScope resolveScope = aClass.getResolveScope(); PsiClass[] supers = aClass.getSupers(); for (int i = 0; i < supers.length; i++) { PsiClass superClass = supers[i]; @@ -122,10 +127,12 @@ public class PsiSuperMethodUtil { if (subType) continue; final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); for (HierarchicalMethodSignature hms : superClass.getVisibleSignatures()) { - final PsiMethod method = hms.getMethod(); + PsiMethod method = hms.getMethod(); if (MethodSignatureUtil.findMethodBySignature(aClass, method.getSignature(superClassSubstitutor), false) != null) continue; - final PsiClass containingClass = method.getContainingClass(); + final PsiClass containingClass = mapClass(method.getContainingClass(), resolveScope); if (containingClass == null) continue; + method = containingClass.findMethodBySignature(method, false); + if (method == null) continue; final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY); if (containingClassSubstitutor == null) continue; final PsiSubstitutor finalSubstitutor = @@ -141,4 +148,30 @@ public class PsiSuperMethodUtil { } return overrideEquivalent; } + + @Nullable + public static PsiClass mapClass(PsiClass psiClass, final GlobalSearchScope resolveScope) { + if (psiClass == null) return null; + String qualifiedName = psiClass.getQualifiedName(); + if (qualifiedName == null) { + return psiClass; + } + + PsiFile file = psiClass.getContainingFile(); + if (file == null || !file.getViewProvider().isPhysical()) { + return psiClass; + } + + final VirtualFile vFile = file.getVirtualFile(); + if (vFile == null) { + return psiClass; + } + + final FileIndexFacade index = FileIndexFacade.getInstance(file.getProject()); + if (!index.isInSource(vFile) && !index.isInLibrarySource(vFile) && !index.isInLibraryClasses(vFile)) { + return psiClass; + } + + return JavaPsiFacade.getInstance(psiClass.getProject()).findClass(qualifiedName, resolveScope); + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java b/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java index f6521658c6dc..d9fcf6bc3c50 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java @@ -15,11 +15,10 @@ */ package com.intellij.psi.impl; -import com.intellij.openapi.roots.FileIndexFacade; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiSuperMethodUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -56,7 +55,7 @@ class TypeCorrector extends PsiTypeMapper { final PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics(); final PsiClass psiClass = classResolveResult.getElement(); if (psiClass != null && classResolveResult.getSubstitutor() == PsiSubstitutor.EMPTY) { - final PsiClass mappedClass = mapClass(psiClass); + final PsiClass mappedClass = PsiSuperMethodUtil.mapClass(psiClass, myResolveScope); if (mappedClass == null || mappedClass == psiClass) return (T) classType; } } @@ -79,7 +78,7 @@ class TypeCorrector extends PsiTypeMapper { PsiUtilCore.ensureValid(psiClass); - final PsiClass mappedClass = mapClass(psiClass); + final PsiClass mappedClass = PsiSuperMethodUtil.mapClass(psiClass, myResolveScope); if (mappedClass == null) return classType; PsiClassType mappedType = new PsiCorrectedClassType(classType.getLanguageLevel(), @@ -89,31 +88,6 @@ class TypeCorrector extends PsiTypeMapper { return mappedType; } - @Nullable - private PsiClass mapClass(@NotNull PsiClass psiClass) { - String qualifiedName = psiClass.getQualifiedName(); - if (qualifiedName == null) { - return psiClass; - } - - PsiFile file = psiClass.getContainingFile(); - if (file == null || !file.getViewProvider().isPhysical()) { - return psiClass; - } - - final VirtualFile vFile = file.getVirtualFile(); - if (vFile == null) { - return psiClass; - } - - final FileIndexFacade index = FileIndexFacade.getInstance(file.getProject()); - if (!index.isInSource(vFile) && !index.isInLibrarySource(vFile) && !index.isInLibraryClasses(vFile)) { - return psiClass; - } - - return JavaPsiFacade.getInstance(psiClass.getProject()).findClass(qualifiedName, myResolveScope); - } - @NotNull private PsiSubstitutor mapSubstitutor(PsiClass originalClass, PsiClass mappedClass, PsiSubstitutor substitutor) { PsiTypeParameter[] typeParameters = mappedClass.getTypeParameters(); diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java new file mode 100644 index 000000000000..30e62b5249e6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java @@ -0,0 +1,4 @@ +package p; +interface I { + default void foo(); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java new file mode 100644 index 000000000000..52e05186d644 --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java @@ -0,0 +1,3 @@ +package p; + +public abstract class A implements I {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java new file mode 100644 index 000000000000..30e62b5249e6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java @@ -0,0 +1,4 @@ +package p; +interface I { + default void foo(); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java new file mode 100644 index 000000000000..ab93746c9c7d --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java @@ -0,0 +1,8 @@ +package p; + +class EmptyValueIterator extends A implements ValueIterator { + +} + +interface ValueIterator extends I {} + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java index 874522ec38f7..4c6c21761f55 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java @@ -18,7 +18,6 @@ package com.intellij.codeInsight; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.module.Module; -import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.pom.java.LanguageLevel; @@ -26,7 +25,6 @@ import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; import com.intellij.testFramework.fixtures.*; -import com.intellij.util.Consumer; public class MultipleJdksHighlightingTest extends UsefulTestCase { @@ -197,6 +195,16 @@ public class MultipleJdksHighlightingTest extends UsefulTestCase { myFixture.checkHighlighting(); } + public void testUnrelatedDefaultsFromDifferentJdkVersions() throws Exception { + ModuleRootModificationUtil.addDependency(myJava8Module, myJava7Module); + myFixture.copyFileToProject("java7/p/I.java"); + myFixture.copyFileToProject("java8/p/I.java"); + + final String testName = getTestName(false); + myFixture.configureByFiles("java8/p/" + testName + ".java", "java7/p/" + testName + ".java"); + myFixture.checkHighlighting(); + } + private void doTestWithoutLibrary() { final String name = getTestName(false); myFixture.configureByFiles("java7/p/" + name + ".java", "java8/p/" + name + ".java"); From 94c2a1c3258aaf58b8fbf0f609cc3cd16b8cb162 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Fri, 24 Jun 2016 15:46:46 +0300 Subject: [PATCH 32/36] Fix tests: we should always check if suspend policy "All" is supported for the breakpoint type. Otherwise we break Django template debugging --- python/src/com/jetbrains/python/debugger/PyDebugProcess.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java index 3ab7886b6237..3570746593d0 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java @@ -533,7 +533,8 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr breakpoint = myRegisteredExceptionBreakpoints.get(exceptionName); } } - if ((breakpoint != null) && (breakpoint.getSuspendPolicy() == SuspendPolicy.ALL)) { + if ((breakpoint != null) && (breakpoint.getType().isSuspendThreadSupported()) && + (breakpoint.getSuspendPolicy() == SuspendPolicy.ALL)) { return true; } } @@ -855,7 +856,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr } } if (breakpoint != null) { - if (breakpoint.getSuspendPolicy() == SuspendPolicy.ALL) { + if ((breakpoint.getType().isSuspendThreadSupported()) && (breakpoint.getSuspendPolicy() == SuspendPolicy.ALL)) { suspendAllOtherThreads(threadInfo); } } From 74276d773abb41c2616dd62a55999c961baf3f76 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 14:44:45 +0200 Subject: [PATCH 33/36] add FileBasedIndexImpl.processAllValues to iterate over file ids --- .../util/indexing/FileBasedIndexImpl.java | 155 +++++++++++------- 1 file changed, 97 insertions(+), 58 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 3ff4aa000ccd..fe96142f26cf 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -767,13 +767,15 @@ public class FileBasedIndexImpl extends FileBasedIndex { } } - processValuesImpl(indexId, dataKey, true, restrictToFile, new ValueProcessor() { - @Override - public boolean process(final VirtualFile file, final V value) { - values.add(value); - return true; - } - }, filter, null); + ValueProcessor processor = (file, value) -> { + values.add(value); + return true; + }; + if (restrictToFile != null) { + processValuesInOneFile(indexId, dataKey, restrictToFile, processor, filter); + } else { + processValuesInScope(indexId, dataKey, true, filter, null, processor); + } return values; } @@ -783,13 +785,10 @@ public class FileBasedIndexImpl extends FileBasedIndex { @NotNull K dataKey, @NotNull final GlobalSearchScope filter) { final Set files = new THashSet(); - processValuesImpl(indexId, dataKey, false, null, new ValueProcessor() { - @Override - public boolean process(final VirtualFile file, final V value) { - files.add(file); - return true; - } - }, filter, null); + processValuesInScope(indexId, dataKey, false, filter, null, (file, value) -> { + files.add(file); + return true; + }); return files; } @@ -807,7 +806,40 @@ public class FileBasedIndexImpl extends FileBasedIndex { @NotNull ValueProcessor processor, @NotNull GlobalSearchScope filter, @Nullable IdFilter idFilter) { - return processValuesImpl(indexId, dataKey, false, inFile, processor, filter, idFilter); + return inFile != null + ? processValuesInOneFile(indexId, dataKey, inFile, processor, filter) + : processValuesInScope(indexId, dataKey, false, filter, idFilter, processor); + } + + public interface IdValueProcessor { + /** + * @param fileId the id of the file that the value came from + * @param value a value to process + * @return false if no further processing is needed, true otherwise + */ + boolean process(int fileId, V value); + } + + /** + * Process values for a given index key together with their containing file ids. Note that project is supplied + * only to ensure that all the indices in that project are up to date; there's no guarantee that the processed file ids belong + * to this project. + */ + public boolean processAllValues(@NotNull ID indexId, + @NotNull K key, + @NotNull Project project, + @NotNull IdValueProcessor processor) { + return processValueIterator(indexId, key, null, GlobalSearchScope.allScope(project), valueIt -> { + while (valueIt.hasNext()) { + V value = valueIt.next(); + for (ValueContainer.IntIterator inputIdsIterator = valueIt.getInputIdsIterator(); inputIdsIterator.hasNext(); ) { + if (!processor.process(inputIdsIterator.next(), value)) { + return false; + } + } + } + return true; + }); } @Nullable @@ -854,54 +886,61 @@ public class FileBasedIndexImpl extends FileBasedIndex { return null; } - private boolean processValuesImpl(@NotNull final ID indexId, @NotNull final K dataKey, final boolean ensureValueProcessedOnce, - @Nullable final VirtualFile restrictToFile, @NotNull final ValueProcessor processor, - @NotNull final GlobalSearchScope scope, @Nullable final IdFilter idFilter) { - ThrowableConvertor, Boolean, StorageException> keyProcessor = - index -> { - final ValueContainer container = index.getData(dataKey); + private boolean processValuesInOneFile(@NotNull ID indexId, + @NotNull K dataKey, + @NotNull VirtualFile restrictToFile, + @NotNull ValueProcessor processor, @NotNull GlobalSearchScope scope) { + if (!(restrictToFile instanceof VirtualFileWithId)) return true; - boolean shouldContinue = true; + int restrictedFileId = getFileId(restrictToFile); + return processValueIterator(indexId, dataKey, restrictToFile, scope, valueIt -> { + while (valueIt.hasNext()) { + V value = valueIt.next(); + if (valueIt.getValueAssociationPredicate().contains(restrictedFileId) && !processor.process(restrictToFile, value)) { + return false; + } + } + return true; + }); + } - if (restrictToFile != null) { - if (restrictToFile instanceof VirtualFileWithId) { - final int restrictedFileId = getFileId(restrictToFile); - for (final ValueContainer.ValueIterator valueIt = container.getValueIterator(); valueIt.hasNext(); ) { - final V value = valueIt.next(); - if (valueIt.getValueAssociationPredicate().contains(restrictedFileId)) { - shouldContinue = processor.process(restrictToFile, value); - if (!shouldContinue) { - break; - } - } + private boolean processValuesInScope(@NotNull ID indexId, + @NotNull K dataKey, + boolean ensureValueProcessedOnce, + @NotNull GlobalSearchScope scope, + @Nullable IdFilter idFilter, + @NotNull ValueProcessor processor) { + PersistentFS fs = (PersistentFS)ManagingFS.getInstance(); + IdFilter filter = idFilter != null ? idFilter : projectIndexableFiles(scope.getProject()); + + return processValueIterator(indexId, dataKey, null, scope, valueIt -> { + while (valueIt.hasNext()) { + final V value = valueIt.next(); + for (final ValueContainer.IntIterator inputIdsIterator = valueIt.getInputIdsIterator(); inputIdsIterator.hasNext(); ) { + final int id = inputIdsIterator.next(); + if (filter != null && !filter.containsFileId(id)) continue; + VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id); + if (file != null && scope.accept(file)) { + if (!processor.process(file, value)) { + return false; + } + if (ensureValueProcessedOnce) { + break; // continue with the next value } } } - else { - final PersistentFS fs = (PersistentFS)ManagingFS.getInstance(); - final IdFilter filter = idFilter != null ? idFilter : projectIndexableFiles(scope.getProject()); - VALUES_LOOP: - for (final ValueContainer.ValueIterator valueIt = container.getValueIterator(); valueIt.hasNext(); ) { - final V value = valueIt.next(); - for (final ValueContainer.IntIterator inputIdsIterator = valueIt.getInputIdsIterator(); inputIdsIterator.hasNext(); ) { - final int id = inputIdsIterator.next(); - if (filter != null && !filter.containsFileId(id)) continue; - VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id); - if (file != null && scope.accept(file)) { - shouldContinue = processor.process(file, value); - if (!shouldContinue) { - break VALUES_LOOP; - } - if (ensureValueProcessedOnce) { - break; // continue with the next value - } - } - } - } - } - return shouldContinue; - }; - final Boolean result = processExceptions(indexId, restrictToFile, scope, keyProcessor); + } + return true; + }); + } + + private boolean processValueIterator(@NotNull ID indexId, + @NotNull K dataKey, + @Nullable VirtualFile restrictToFile, + @NotNull GlobalSearchScope scope, + @NotNull Processor> valueProcessor) { + final Boolean result = processExceptions(indexId, restrictToFile, scope, + index -> valueProcessor.process(index.getData(dataKey).getValueIterator())); return result == null || result.booleanValue(); } From 95b3d482d95c27dbb065a5d47c1de2133a85e39b Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 14:57:17 +0200 Subject: [PATCH 34/36] more efficient use of indices in stub hierarchy --- .../impl/HierarchyServiceImpl.java | 71 ++++++++++++------- .../stubsHierarchy/impl/JavaStubIndexer.java | 10 +-- .../impl/StubHierarchyIndex.java | 35 ++++----- .../java/stubs/index/JavaUnitDescriptor.java | 4 +- .../stubsHierarchy/StubHierarchyIndexer.java | 5 +- .../impl/java/stubs/hierarchy/IndexTree.java | 18 ++++- .../psi/stubs/hierarchy/GrStubIndexer.java | 12 ++-- 7 files changed, 92 insertions(+), 63 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java index 31fa42faa53a..654729f0d1ba 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java @@ -19,13 +19,11 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileWithId; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; -import com.intellij.psi.search.DelegatingGlobalSearchScope; -import com.intellij.psi.search.EverythingGlobalScope; -import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.stubsHierarchy.HierarchyService; import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; @@ -33,17 +31,18 @@ import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.util.CachedValueBase; import com.intellij.util.indexing.FileBasedIndex; +import com.intellij.util.indexing.FileBasedIndexImpl; import org.jetbrains.annotations.NotNull; +import java.util.BitSet; + public class HierarchyServiceImpl extends HierarchyService { private static final SingleClassHierarchy EMPTY_HIERARCHY = new SingleClassHierarchy(Symbol.ClassSymbol.EMPTY_ARRAY); private final Project myProject; - private final ProjectFileIndex myFileIndex; private final CachedValue myHierarchy; public HierarchyServiceImpl(Project project) { myProject = project; - myFileIndex = ProjectFileIndex.SERVICE.getInstance(project); myHierarchy = CachedValuesManager.getManager(project).createCachedValue( () -> CachedValueProvider.Result.create(buildHierarchy(), PsiModificationTracker.MODIFICATION_COUNT), false); @@ -69,38 +68,56 @@ public class HierarchyServiceImpl extends HierarchyService { private SingleClassHierarchy buildHierarchy() { Symbols symbols = new Symbols(); StubEnter stubEnter = new StubEnter(symbols); + IdSets idSets = IdSets.getIdSets(myProject); - loadUnits(false, symbols.myNameEnvironment, stubEnter); + loadUnits(idSets.libraryFiles, StubHierarchyIndex.BINARY_FILES, symbols.myNameEnvironment, stubEnter); stubEnter.connect1(); - loadUnits(true, symbols.myNameEnvironment, stubEnter); + loadUnits(idSets.sourceFiles, StubHierarchyIndex.SOURCE_FILES, symbols.myNameEnvironment, stubEnter); stubEnter.connect2(); return symbols.createHierarchy(); } - private void loadUnits(boolean sourceMode, NameEnvironment names, StubEnter stubEnter) { - GlobalSearchScope scope = new DelegatingGlobalSearchScope(new EverythingGlobalScope(myProject)) { - @Override - public boolean contains(@NotNull VirtualFile file) { - return sourceMode ? myFileIndex.isInSourceContent(file) : myFileIndex.isInLibraryClasses(file); - } - }; + private void loadUnits(BitSet files, int indexKey, NameEnvironment names, StubEnter stubEnter) { ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator(); - FileBasedIndex index = FileBasedIndex.getInstance(); - for (String packageName : index.getAllKeys(StubHierarchyIndex.INDEX_ID, myProject)) { - QualifiedName pkg = StringUtil.isEmpty(packageName) ? null : names.fromString(packageName, true); - index.processValues(StubHierarchyIndex.INDEX_ID, packageName, null, new FileBasedIndex.ValueProcessor() { - int count = 0; - @Override - public boolean process(VirtualFile file, IndexTree.Unit unit) { - if (indicator != null && ++count % 128 == 0) indicator.checkCanceled(); - stubEnter.unitEnter(Translator.internNames(names, unit, ((VirtualFileWithId)file).getId(), pkg)); - return true; + FileBasedIndexImpl index = (FileBasedIndexImpl)FileBasedIndex.getInstance(); + index.processAllValues(StubHierarchyIndex.INDEX_ID, indexKey, myProject, new FileBasedIndexImpl.IdValueProcessor() { + int count = 0; + @Override + public boolean process(int fileId, IndexTree.Unit unit) { + if (indicator != null && ++count % 128 == 0) indicator.checkCanceled(); + if (files.get(fileId)) { + QualifiedName pkg = StringUtil.isEmpty(unit.myPackageId) ? null : names.fromString(unit.myPackageId, true); + stubEnter.unitEnter(Translator.internNames(names, unit, fileId, pkg)); } - }, scope); - } + return true; + } + }); } + private static class IdSets { + final BitSet sourceFiles = new BitSet(); + final BitSet libraryFiles = new BitSet(); + + static IdSets getIdSets(@NotNull Project project) { + return CachedValuesManager.getManager(project).getCachedValue(project, () -> { + IdSets answer = new IdSets(); + ProjectFileIndex index = ProjectFileIndex.SERVICE.getInstance(project); + FileBasedIndex.getInstance().iterateIndexableFiles(file -> { + if (!file.isDirectory() && file instanceof VirtualFileWithId) { + if (index.isInSourceContent(file)) { + answer.sourceFiles.set(((VirtualFileWithId) file).getId()); + } + else if (index.isInLibraryClasses(file)) { + answer.libraryFiles.set(((VirtualFileWithId) file).getId()); + } + } + return true; + }, project, ProgressIndicatorProvider.getGlobalProgressIndicator()); + return CachedValueProvider.Result.create(answer, ProjectRootManager.getInstance(project), VirtualFileManager.VFS_STRUCTURE_MODIFICATIONS); + }); + } + } } diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java index 550c33b9c74e..616ea7213f3c 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java @@ -18,7 +18,6 @@ package com.intellij.psi.stubsHierarchy.impl; import com.intellij.ide.highlighter.JavaClassFileType; import com.intellij.ide.highlighter.JavaFileType; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiNameHelper; @@ -39,7 +38,10 @@ import com.intellij.util.indexing.FileContent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class JavaStubIndexer extends StubHierarchyIndexer { @@ -61,7 +63,7 @@ public class JavaStubIndexer extends StubHierarchyIndexer { @Nullable @Override - public List> indexFile(@NotNull FileContent content) { + public Unit indexFile(@NotNull FileContent content) { Stub stubTree = StubTreeBuilder.buildStubTree(content); if (!(stubTree instanceof PsiJavaFileStub)) return null; @@ -87,7 +89,7 @@ public class JavaStubIndexer extends StubHierarchyIndexer { ClassDecl[] classes = classList.isEmpty() ? ClassDecl.EMPTY_ARRAY : classList.toArray(new ClassDecl[classList.size()]); Import[] imports = importList.isEmpty() ? Import.EMPTY_ARRAY : importList.toArray(new Import[importList.size()]); byte type = javaFileStub.isCompiled() ? IndexTree.BYTECODE : IndexTree.JAVA; - return Collections.singletonList(Pair.create(javaFileStub.getPackageName(), new Unit(type, imports, classes))); + return new Unit(javaFileStub.getPackageName(), type, imports, classes); } @Nullable diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java index 2550e2fb528a..269bf9fa1f1a 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java @@ -18,47 +18,42 @@ package com.intellij.psi.stubsHierarchy.impl; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.ProjectFileIndex; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; import com.intellij.psi.impl.java.stubs.index.JavaUnitDescriptor; import com.intellij.psi.stubsHierarchy.StubHierarchyIndexer; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; -import com.intellij.util.io.EnumeratorStringDescriptor; +import com.intellij.util.io.EnumeratorIntegerDescriptor; import com.intellij.util.io.KeyDescriptor; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; /** * @author peter */ -public class StubHierarchyIndex extends FileBasedIndexExtension implements PsiDependentIndex { - static final ID INDEX_ID = ID.create("jvm.hierarchy"); +public class StubHierarchyIndex extends FileBasedIndexExtension implements PsiDependentIndex { + public static final int BINARY_FILES = 0; + public static final int SOURCE_FILES = 1; + static final ID INDEX_ID = ID.create("jvm.hierarchy"); private static final StubHierarchyIndexer[] ourIndexers = StubHierarchyIndexer.EP_NAME.getExtensions(); @NotNull @Override - public ID getName() { + public ID getName() { return INDEX_ID; } @NotNull @Override - public DataIndexer getIndexer() { + public DataIndexer getIndexer() { return inputData -> { for (StubHierarchyIndexer indexer : ourIndexers) { - List> pairs = indexer.handlesFile(inputData.getFile()) ? indexer.indexFile(inputData) : null; - if (pairs != null && !pairs.isEmpty()) { - Map answer = new HashMap<>(); - for (Pair entry : pairs) { - if (entry.second.myDecls.length > 0) { - answer.put(StringUtil.notNullize(entry.first), entry.second); - } - } - return answer; + IndexTree.Unit unit = indexer.handlesFile(inputData.getFile()) ? indexer.indexFile(inputData) : null; + if (unit != null && unit.myDecls.length > 0) { + return Collections.singletonMap(inputData.getFile().getFileType().isBinary() ? BINARY_FILES : SOURCE_FILES, unit); } } return Collections.emptyMap(); @@ -67,8 +62,8 @@ public class StubHierarchyIndex extends FileBasedIndexExtension getKeyDescriptor() { - return EnumeratorStringDescriptor.INSTANCE; + public KeyDescriptor getKeyDescriptor() { + return EnumeratorIntegerDescriptor.INSTANCE; } @NotNull @@ -79,7 +74,7 @@ public class StubHierarchyIndex extends FileBasedIndexExtension { @Override public void save(@NotNull DataOutput out, IndexTree.Unit value) throws IOException { + out.writeUTF(value.myPackageId); out.writeByte(value.myUnitType); if (value.myUnitType != IndexTree.BYTECODE) { DataInputOutputUtil.writeINT(out, value.imports.length); @@ -75,6 +76,7 @@ public class JavaUnitDescriptor implements DataExternalizer { @Override public IndexTree.Unit read(@NotNull DataInput in) throws IOException { + String pid = in.readUTF(); byte type = in.readByte(); IndexTree.Import[] imports = IndexTree.Import.EMPTY_ARRAY; if (type != IndexTree.BYTECODE) { @@ -87,7 +89,7 @@ public class JavaUnitDescriptor implements DataExternalizer { for (int i = 0; i < classes.length; i++) { classes[i] = readClassDecl(in); } - return new IndexTree.Unit(type, imports, classes); + return new IndexTree.Unit(pid, type, imports, classes); } private IndexTree.ClassDecl readClassDecl(DataInput in) throws IOException { diff --git a/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/StubHierarchyIndexer.java b/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/StubHierarchyIndexer.java index ce9d16602224..4e0e8ac260fc 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/StubHierarchyIndexer.java +++ b/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/StubHierarchyIndexer.java @@ -16,15 +16,12 @@ package com.intellij.psi.stubsHierarchy; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; import com.intellij.util.indexing.FileContent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - /** * @author peter */ @@ -37,7 +34,7 @@ public abstract class StubHierarchyIndexer { * @return a list of pairs for a specified file content */ @Nullable - public abstract List> indexFile(@NotNull FileContent content); + public abstract IndexTree.Unit indexFile(@NotNull FileContent content); public abstract boolean handlesFile(@NotNull VirtualFile file); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java index faf27c3a2d7b..fdf452e9af91 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java @@ -17,6 +17,9 @@ package com.intellij.psi.impl.java.stubs.hierarchy; import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -37,11 +40,13 @@ public class IndexTree { public static final byte GROOVY = 2; public static class Unit { + @NotNull public final String myPackageId; public final byte myUnitType; public final Import[] imports; public final ClassDecl[] myDecls; - public Unit(byte unitType, Import[] imports, ClassDecl[] decls) { + public Unit(@Nullable String packageId, byte unitType, Import[] imports, ClassDecl[] decls) { + this.myPackageId = StringUtil.notNullize(packageId); this.myUnitType = unitType; this.imports = imports; this.myDecls = decls; @@ -54,6 +59,8 @@ public class IndexTree { Unit unit = (Unit)o; + if (myUnitType != unit.myUnitType) return false; + if (!myPackageId.equals(unit.myPackageId)) return false; if (!Arrays.equals(imports, unit.imports)) return false; if (!Arrays.equals(myDecls, unit.myDecls)) return false; @@ -62,7 +69,14 @@ public class IndexTree { @Override public int hashCode() { - return Arrays.hashCode(myDecls); + int hash = myUnitType * 31 + myPackageId.hashCode(); + for (ClassDecl decl : myDecls) { + String name = decl.myName; + if (name != null) { + return hash * 31 + name.hashCode(); + } + } + return hash; } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/hierarchy/GrStubIndexer.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/hierarchy/GrStubIndexer.java index 2a9303c09d62..c124aae6cc20 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/hierarchy/GrStubIndexer.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/hierarchy/GrStubIndexer.java @@ -15,7 +15,6 @@ */ package org.jetbrains.plugins.groovy.lang.psi.stubs.hierarchy; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiNameHelper; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; @@ -33,7 +32,10 @@ import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.stubs.*; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class GrStubIndexer extends StubHierarchyIndexer { @Override @@ -48,14 +50,14 @@ public class GrStubIndexer extends StubHierarchyIndexer { @Nullable @Override - public List> indexFile(@NotNull FileContent content) { + public Unit indexFile(@NotNull FileContent content) { Stub stubTree = StubTreeBuilder.buildStubTree(content); if (!(stubTree instanceof GrFileStub)) return null; GrFileStub grFileStub = (GrFileStub)stubTree; new StubTree(grFileStub, false); - String pid = null; + String pid = ""; ArrayList classList = new ArrayList(); Set usedNames = new HashSet(); for (StubElement el : grFileStub.getChildrenStubs()) { @@ -82,7 +84,7 @@ public class GrStubIndexer extends StubHierarchyIndexer { } ClassDecl[] classes = classList.isEmpty() ? ClassDecl.EMPTY_ARRAY : classList.toArray(new ClassDecl[classList.size()]); Import[] imports = importList.isEmpty() ? Import.EMPTY_ARRAY : importList.toArray(new Import[importList.size()]); - return Collections.singletonList(Pair.create(pid, new Unit(IndexTree.GROOVY, imports, classes))); + return new Unit(pid, IndexTree.GROOVY, imports, classes); } @Nullable From daf076085a848aff02008c60808e2fe717474c00 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Fri, 24 Jun 2016 15:59:22 +0300 Subject: [PATCH 35/36] Fix NPE in test (PY-16825) --- .../python/console/PythonConsoleView.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java index 32b4dc981093..98a25946f70b 100644 --- a/python/src/com/jetbrains/python/console/PythonConsoleView.java +++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java @@ -96,12 +96,14 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable } public void inputRequested() { - final ConsoleCommunication consoleCommunication = myExecuteActionHandler.getConsoleCommunication(); - if (consoleCommunication instanceof PythonDebugConsoleCommunication) { - ((PythonDebugConsoleCommunication)consoleCommunication).waitingForInput = true; - myExecuteActionHandler.inputRequested(); - myExecuteActionHandler.setEnabled(true); - myExecuteActionHandler.clearInputBuffer(); + if (myExecuteActionHandler != null) { + final ConsoleCommunication consoleCommunication = myExecuteActionHandler.getConsoleCommunication(); + if (consoleCommunication instanceof PythonDebugConsoleCommunication) { + ((PythonDebugConsoleCommunication)consoleCommunication).waitingForInput = true; + myExecuteActionHandler.inputRequested(); + myExecuteActionHandler.setEnabled(true); + myExecuteActionHandler.clearInputBuffer(); + } } } From a63c3e539c29e9673a9c89acfb11792cc5bcb818 Mon Sep 17 00:00:00 2001 From: Alexander Koshevoy Date: Fri, 24 Jun 2016 16:03:24 +0300 Subject: [PATCH 36/36] PY-18843 Remote Python SDKs are not considered as candidates for base SDKs for virtual envs --- python/src/com/jetbrains/python/sdk/PythonSdkType.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index f45a1331e6b7..f4e78a80c7c8 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -59,7 +59,6 @@ import com.intellij.remote.ext.LanguageCaseCollector; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.ExceptionUtil; -import com.intellij.util.NullableConsumer; import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; @@ -322,9 +321,11 @@ public final class PythonSdkType extends SdkType { final String version = getVersionString(sdk); if (flavor != null && version != null) { for (Sdk baseSdk : getAllSdks()) { - final PythonSdkFlavor baseFlavor = PythonSdkFlavor.getFlavor(baseSdk); - if (!isVirtualEnv(baseSdk) && flavor.equals(baseFlavor) && version.equals(getVersionString(baseSdk))) { - return baseSdk; + if (!isRemote(baseSdk)) { + final PythonSdkFlavor baseFlavor = PythonSdkFlavor.getFlavor(baseSdk); + if (!isVirtualEnv(baseSdk) && flavor.equals(baseFlavor) && version.equals(getVersionString(baseSdk))) { + return baseSdk; + } } } }