From 4e1ef49c2806977cd907cffc7ebee0b48ef21082 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 10 Mar 2014 15:03:35 +0100 Subject: [PATCH 01/32] cleanup --- .../debugger/impl/DescriptorTestCase.java | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java index 0d6624d9894b..a3ad0c55ceab 100644 --- a/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java +++ b/java/testFramework/src/com/intellij/debugger/impl/DescriptorTestCase.java @@ -34,7 +34,10 @@ import com.intellij.execution.process.ProcessOutputTypes; import com.intellij.openapi.util.Pair; import com.sun.jdi.Value; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public abstract class DescriptorTestCase extends DebuggerTestCase { private final List>> myDescriptorLog = new ArrayList>>(); @@ -51,10 +54,9 @@ public abstract class DescriptorTestCase extends DebuggerTestCase { return getAlternateCollectionRenderer("Map"); } - private NodeRenderer getAlternateCollectionRenderer(final String name) { + private static NodeRenderer getAlternateCollectionRenderer(final String name) { final NodeRenderer[] renderers = NodeRendererSettings.getInstance().getAlternateCollectionRenderers(); - for (int idx = 0; idx < renderers.length; idx++) { - NodeRenderer renderer = renderers[idx]; + for (NodeRenderer renderer : renderers) { if (name.equals(renderer.getName())) { return renderer; } @@ -105,9 +107,8 @@ public abstract class DescriptorTestCase extends DebuggerTestCase { private Pair> findDescriptorLog(final NodeDescriptorImpl descriptor) { Pair> descriptorText = null; - for (Iterator>> iterator = myDescriptorLog.iterator(); iterator.hasNext();) { - Pair> pair = iterator.next(); - if(pair.getFirst() == descriptor) { + for (Pair> pair : myDescriptorLog) { + if (pair.getFirst() == descriptor) { descriptorText = pair; break; } @@ -115,24 +116,15 @@ public abstract class DescriptorTestCase extends DebuggerTestCase { return descriptorText; } - protected void flushDescriptor(final NodeDescriptorImpl descriptor) { - Pair> descriptorLog = findDescriptorLog(descriptor); - if(descriptorLog != null) { - printDescriptorLog(descriptorLog); - myDescriptorLog.remove(descriptorLog); - } - } - protected void flushDescriptors() { - for (Iterator>> iterator = myDescriptorLog.iterator(); iterator.hasNext();) { - printDescriptorLog(iterator.next()); + for (Pair> aMyDescriptorLog : myDescriptorLog) { + printDescriptorLog(aMyDescriptorLog); } myDescriptorLog.clear(); } private void printDescriptorLog(Pair> pair) { - for (Iterator it = pair.getSecond().iterator(); it.hasNext();) { - String text = it.next(); + for (String text : pair.getSecond()) { print(text, ProcessOutputTypes.SYSTEM); } } @@ -150,6 +142,7 @@ public abstract class DescriptorTestCase extends DebuggerTestCase { String name) { try { StackFrameProxy frameProxy = evaluationContext.getFrameProxy(); + assert frameProxy != null; LocalVariableDescriptorImpl local = frameTree.getNodeFactory().getLocalVariableDescriptor(null, frameProxy.visibleVariableByName(name)); local.setContext(evaluationContext); return local; @@ -169,7 +162,7 @@ public abstract class DescriptorTestCase extends DebuggerTestCase { doExpandAll(tree, runnable, new HashSet(), null); } - protected static interface NodeFilter { + protected interface NodeFilter { boolean shouldExpand(DebuggerTreeNode node); } @@ -186,7 +179,7 @@ public abstract class DescriptorTestCase extends DebuggerTestCase { final DebuggerTreeNode treeNode = (DebuggerTreeNode)tree.getPathForRow(i).getLastPathComponent(); if(tree.isCollapsed(i) && !treeNode.isLeaf()) { final NodeDescriptor nodeDescriptor = treeNode.getDescriptor(); - boolean shouldExpand = filter == null? true : filter.shouldExpand(treeNode); + boolean shouldExpand = filter == null || filter.shouldExpand(treeNode); if (shouldExpand) { // additional checks to prevent infinite expand if (nodeDescriptor instanceof ValueDescriptor) { From 010566a6710b5e1d61f6936d5753b3b77ff8185c Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 10 Mar 2014 15:23:40 +0100 Subject: [PATCH 02/32] IDEA-58818 (SSR: strange highlighting of try-catch in preview pane) --- .../src/com/intellij/usages/impl/UsagePreviewPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java b/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java index e2c023d360bc..326bbecf1596 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java @@ -126,7 +126,7 @@ public class UsagePreviewPanel extends UsageContextPanelBase { TextRange elementRange = psiElement.getTextRange(); TextRange infoRange = info.getRangeInElement(); - TextRange textRange = infoRange == null ? null : elementRange.intersection(infoRange); + TextRange textRange = infoRange == null ? null : elementRange.cutOut(infoRange); if (textRange == null) textRange = elementRange; // hack to determine element range to highlight if (psiElement instanceof PsiNamedElement && !(psiElement instanceof PsiFile)) { From 20d9cb0d4a1e0348224c8654c506dcb29bde29fd Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 10 Mar 2014 15:54:46 +0100 Subject: [PATCH 03/32] make public --- .../src/com/intellij/execution/actions/ExecutorProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/actions/ExecutorProvider.java b/platform/lang-impl/src/com/intellij/execution/actions/ExecutorProvider.java index 7f0fa25d6704..76ee20454fea 100644 --- a/platform/lang-impl/src/com/intellij/execution/actions/ExecutorProvider.java +++ b/platform/lang-impl/src/com/intellij/execution/actions/ExecutorProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,6 @@ import com.intellij.execution.Executor; /** * User: Vassiliy.Kudryashov */ -interface ExecutorProvider { +public interface ExecutorProvider { Executor getExecutor(); } From 5717d3a63b4b0e407625211f33687c800dd2a618 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 10 Mar 2014 15:56:06 +0100 Subject: [PATCH 04/32] make public and refactor to make accessible from Search Everywhere --- .../actions/ChooseRunConfigurationPopup.java | 420 +++++++++--------- 1 file changed, 212 insertions(+), 208 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java index 2f8b7c51533e..1a0235ac9d46 100644 --- a/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java +++ b/platform/lang-impl/src/com/intellij/execution/actions/ChooseRunConfigurationPopup.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,6 @@ import com.intellij.ide.util.PropertiesComponent; import com.intellij.idea.ActionsBundle; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.ListPopupStep; @@ -53,7 +52,7 @@ import java.awt.event.MouseEvent; import java.util.*; import java.util.List; -class ChooseRunConfigurationPopup implements ExecutorProvider { +public class ChooseRunConfigurationPopup implements ExecutorProvider { private final Project myProject; @NotNull private final String myAddKey; @@ -304,7 +303,7 @@ class ChooseRunConfigurationPopup implements ExecutorProvider { } } - private abstract static class ItemWrapper extends Wrapper { + public abstract static class ItemWrapper extends Wrapper { private final T myValue; private boolean myDynamic; @@ -430,7 +429,7 @@ class ChooseRunConfigurationPopup implements ExecutorProvider { @NotNull final Project project, @NotNull final ExecutorProvider executorProvider, @NotNull final String title) { - super(title, createSettingsList(project, executorProvider)); + super(title, createSettingsList(project, executorProvider, true)); myProject = project; myAction = action; @@ -456,209 +455,6 @@ class ChooseRunConfigurationPopup implements ExecutorProvider { return false; } - private static ItemWrapper[] createSettingsList(@NotNull final Project project, @NotNull ExecutorProvider executorProvider) { - final RunManagerEx manager = RunManagerEx.getInstanceEx(project); - - final List result = new ArrayList(); - - final RunnerAndConfigurationSettings selectedConfiguration = manager.getSelectedConfiguration(); - - if (selectedConfiguration != null) { - boolean isFirst = true; - final ExecutionTarget activeTarget = ExecutionTargetManager.getActiveTarget(project); - for (final ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, selectedConfiguration)) { - result.add(new ItemWrapper(eachTarget, isFirst) { - { - setChecked(eachTarget.equals(activeTarget)); - } - - @Override - public Icon getIcon() { - return eachTarget.getIcon(); - } - - @Override - public String getText() { - return eachTarget.getDisplayName(); - } - - @Override - public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) { - ExecutionTargetManager.setActiveTarget(project, eachTarget); - doRunConfiguration(selectedConfiguration, executor, project); - } - - @Override - public boolean available(Executor executor) { - return true; - } - }); - isFirst = false; - } - } - - - final Map wrappedExisting = new LinkedHashMap(); - final ConfigurationType[] types = manager.getConfigurationFactories(); - for (final ConfigurationType type : types) { - if (!(type instanceof UnknownConfigurationType)) { - Map> structure = manager.getStructure(type); - for (final Map.Entry> entry : structure.entrySet()) { - if (entry.getValue().isEmpty()) - continue; - final String key = entry.getKey(); - if (key != null){ - boolean isSelected = entry.getValue().contains(selectedConfiguration); - FolderWrapper folderWrapper = new FolderWrapper(project, executorProvider, key + (isSelected ? " (mnemonic is to \"" + selectedConfiguration.getName()+"\")" : ""), entry.getValue()); - if (isSelected) { - folderWrapper.setMnemonic(1); - } - result.add(folderWrapper); - } - else { - for (RunnerAndConfigurationSettings configuration : entry.getValue()) { - final ItemWrapper wrapped = ItemWrapper.wrap(project, configuration); - if (configuration == selectedConfiguration) { - wrapped.setMnemonic(1); - } - wrappedExisting.put(configuration, wrapped); - } - } - } - } - } - - populateWithDynamicRunners(result, wrappedExisting, project, manager, selectedConfiguration); - result.addAll(wrappedExisting.values()); - - //noinspection unchecked - final ItemWrapper edit = new ItemWrapper(null) { - @Override - public Icon getIcon() { - return AllIcons.Actions.EditSource; - } - - @Override - public String getText() { - return UIUtil.removeMnemonic(ActionsBundle.message("action.editRunConfigurations.text")); - } - - @Override - public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) { - final EditConfigurationsDialog dialog = new EditConfigurationsDialog(project) { - @Override - protected void init() { - setOKButtonText(executor.getStartActionText()); - setOKButtonIcon(executor.getIcon()); - myExecutor = executor; - super.init(); - } - }; - - dialog.show(); - if (dialog.isOK()) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - doRunConfiguration(RunManager.getInstance(project).getSelectedConfiguration(), executor, project); - } - }); - } - } - - @Override - public boolean available(Executor executor) { - return true; - } - }; - - edit.setMnemonic(0); - result.add(0, edit); - - return result.toArray(new ItemWrapper[result.size()]); - } - - @NotNull - private static List populateWithDynamicRunners(final List result, - Map existing, - final Project project, final RunManagerEx manager, - final RunnerAndConfigurationSettings selectedConfiguration) { - - final ArrayList contextConfigurations = new ArrayList(); - final DataContext dataContext = DataManager.getInstance().getDataContext(); - final ConfigurationContext context = ConfigurationContext.getFromContext(dataContext); - - final List producers = PreferredProducerFind.getConfigurationsFromContext(context.getLocation(), - context, false); - if (producers == null) return Collections.emptyList(); - - Collections.sort(producers, ConfigurationFromContext.NAME_COMPARATOR); - - final RunnerAndConfigurationSettings[] preferred = {null}; - - int i = 2; // selectedConfiguration == null ? 1 : 2; - for (final ConfigurationFromContext fromContext : producers) { - final RunnerAndConfigurationSettings configuration = fromContext.getConfigurationSettings(); - if (existing.keySet().contains(configuration)) { - final ItemWrapper wrapper = existing.get(configuration); - if (wrapper.getMnemonic() != 1) { - wrapper.setMnemonic(i); - i++; - } - } - else { - if (selectedConfiguration != null && configuration.equals(selectedConfiguration)) continue; - contextConfigurations.add(configuration); - - if (preferred[0] == null) { - preferred[0] = configuration; - } - - //noinspection unchecked - final ItemWrapper wrapper = new ItemWrapper(configuration) { - @Override - public Icon getIcon() { - return RunManagerEx.getInstanceEx(project).getConfigurationIcon(configuration); - } - - @Override - public String getText() { - return configuration.getName(); - } - - @Override - public boolean available(Executor executor) { - return canRun(executor, configuration); - } - - @Override - public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) { - manager.setTemporaryConfiguration(configuration); - RunManagerEx.getInstanceEx(project).setSelectedConfiguration(configuration); - doRunConfiguration(configuration, executor, project); - } - - @Override - public PopupStep getNextStep(@NotNull final Project project, @NotNull final ChooseRunConfigurationPopup action) { - return new ConfigurationActionsStep(project, action, configuration, isDynamic()); - } - - @Override - public boolean hasActions() { - return true; - } - }; - - wrapper.setDynamic(true); - wrapper.setMnemonic(i); - result.add(wrapper); - i++; - } - } - - return contextConfigurations; - } - @Override public ListSeparator getSeparatorAbove(ItemWrapper value) { if (value.addSeparatorAbove()) return new ListSeparator(); @@ -1135,4 +931,212 @@ class ChooseRunConfigurationPopup implements ExecutorProvider { return !selectedValue.getValues().isEmpty(); } } + + public static ItemWrapper[] createSettingsList(@NotNull final Project project, @NotNull ExecutorProvider executorProvider, boolean createEditAction) { + final RunManagerEx manager = RunManagerEx.getInstanceEx(project); + + final List result = new ArrayList(); + + final RunnerAndConfigurationSettings selectedConfiguration = manager.getSelectedConfiguration(); + + if (selectedConfiguration != null) { + boolean isFirst = true; + final ExecutionTarget activeTarget = ExecutionTargetManager.getActiveTarget(project); + for (final ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, selectedConfiguration)) { + result.add(new ItemWrapper(eachTarget, isFirst) { + { + setChecked(eachTarget.equals(activeTarget)); + } + + @Override + public Icon getIcon() { + return eachTarget.getIcon(); + } + + @Override + public String getText() { + return eachTarget.getDisplayName(); + } + + @Override + public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) { + ExecutionTargetManager.setActiveTarget(project, eachTarget); + doRunConfiguration(selectedConfiguration, executor, project); + } + + @Override + public boolean available(Executor executor) { + return true; + } + }); + isFirst = false; + } + } + + final Map wrappedExisting = new LinkedHashMap(); + final ConfigurationType[] types = manager.getConfigurationFactories(); + for (final ConfigurationType type : types) { + if (!(type instanceof UnknownConfigurationType)) { + Map> structure = manager.getStructure(type); + for (final Map.Entry> entry : structure.entrySet()) { + if (entry.getValue().isEmpty()) + continue; + final String key = entry.getKey(); + if (key != null){ + boolean isSelected = entry.getValue().contains(selectedConfiguration); + FolderWrapper folderWrapper = new FolderWrapper(project, executorProvider, key + (isSelected ? " (mnemonic is to \"" + selectedConfiguration.getName()+"\")" : ""), entry.getValue()); + if (isSelected) { + folderWrapper.setMnemonic(1); + } + result.add(folderWrapper); + } + else { + for (RunnerAndConfigurationSettings configuration : entry.getValue()) { + final ItemWrapper wrapped = ItemWrapper.wrap(project, configuration); + if (configuration == selectedConfiguration) { + wrapped.setMnemonic(1); + } + wrappedExisting.put(configuration, wrapped); + } + } + } + } + } + + populateWithDynamicRunners(result, wrappedExisting, project, manager, selectedConfiguration); + result.addAll(wrappedExisting.values()); + + //noinspection unchecked + final ItemWrapper edit = new ItemWrapper(null) { + @Override + public Icon getIcon() { + return AllIcons.Actions.EditSource; + } + + @Override + public String getText() { + return UIUtil.removeMnemonic(ActionsBundle.message("action.editRunConfigurations.text")); + } + + @Override + public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) { + final EditConfigurationsDialog dialog = new EditConfigurationsDialog(project) { + @Override + protected void init() { + setOKButtonText(executor.getStartActionText()); + setOKButtonIcon(executor.getIcon()); + myExecutor = executor; + super.init(); + } + }; + + dialog.show(); + if (dialog.isOK()) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + doRunConfiguration(RunManager.getInstance(project).getSelectedConfiguration(), executor, project); + } + }); + } + } + + @Override + public boolean available(Executor executor) { + return true; + } + }; + + edit.setMnemonic(0); + if (createEditAction) { + result.add(0, edit); + } + + return result.toArray(new ItemWrapper[result.size()]); + } + + @NotNull + private static List populateWithDynamicRunners(final List result, + Map existing, + final Project project, final RunManagerEx manager, + final RunnerAndConfigurationSettings selectedConfiguration) { + + final ArrayList contextConfigurations = new ArrayList(); + if (!EventQueue.isDispatchThread()) { + return Collections.emptyList(); + } + + final DataContext dataContext = DataManager.getInstance().getDataContext(); + final ConfigurationContext context = ConfigurationContext.getFromContext(dataContext); + + final List producers = PreferredProducerFind.getConfigurationsFromContext(context.getLocation(), + context, false); + if (producers == null) return Collections.emptyList(); + + Collections.sort(producers, ConfigurationFromContext.NAME_COMPARATOR); + + final RunnerAndConfigurationSettings[] preferred = {null}; + + int i = 2; // selectedConfiguration == null ? 1 : 2; + for (final ConfigurationFromContext fromContext : producers) { + final RunnerAndConfigurationSettings configuration = fromContext.getConfigurationSettings(); + if (existing.keySet().contains(configuration)) { + final ItemWrapper wrapper = existing.get(configuration); + if (wrapper.getMnemonic() != 1) { + wrapper.setMnemonic(i); + i++; + } + } + else { + if (selectedConfiguration != null && configuration.equals(selectedConfiguration)) continue; + contextConfigurations.add(configuration); + + if (preferred[0] == null) { + preferred[0] = configuration; + } + + //noinspection unchecked + final ItemWrapper wrapper = new ItemWrapper(configuration) { + @Override + public Icon getIcon() { + return RunManagerEx.getInstanceEx(project).getConfigurationIcon(configuration); + } + + @Override + public String getText() { + return configuration.getName(); + } + + @Override + public boolean available(Executor executor) { + return canRun(executor, configuration); + } + + @Override + public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) { + manager.setTemporaryConfiguration(configuration); + RunManagerEx.getInstanceEx(project).setSelectedConfiguration(configuration); + doRunConfiguration(configuration, executor, project); + } + + @Override + public PopupStep getNextStep(@NotNull final Project project, @NotNull final ChooseRunConfigurationPopup action) { + return new ConfigurationActionsStep(project, action, configuration, isDynamic()); + } + + @Override + public boolean hasActions() { + return true; + } + }; + + wrapper.setDynamic(true); + wrapper.setMnemonic(i); + result.add(wrapper); + i++; + } + } + + return contextConfigurations; + } } From d7464eef35293fa88d71979c2efb1781f5b43134 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 10 Mar 2014 15:57:42 +0100 Subject: [PATCH 05/32] support run configurations --- .../ide/actions/SearchEverywhereAction.java | 178 ++++++++++++++++-- 1 file changed, 161 insertions(+), 17 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index 44b57802e88d..49231e1bf7a4 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -16,6 +16,11 @@ package com.intellij.ide.actions; import com.intellij.codeInsight.navigation.NavigationUtil; +import com.intellij.execution.Executor; +import com.intellij.execution.ExecutorRegistry; +import com.intellij.execution.actions.ChooseRunConfigurationPopup; +import com.intellij.execution.actions.ExecutorProvider; +import com.intellij.execution.executors.DefaultRunExecutor; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; @@ -66,6 +71,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFilePathWrapper; import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.WindowManager; import com.intellij.openapi.wm.impl.IdeFrameImpl; @@ -115,6 +121,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA public static final int SEARCH_FIELD_COLUMNS = 25; private static final int MAX_CLASSES = 6; private static final int MAX_FILES = 6; + private static final int MAX_RUN_CONFIGURATION = 6; private static final int MAX_TOOL_WINDOWS = 4; private static final int MAX_SYMBOLS = 6; private static final int MAX_SETTINGS = 5; @@ -149,6 +156,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA private AnActionEvent myActionEvent; private Component myContextComponent; private CalcThread myCalcThread; + private static AtomicBoolean ourShiftIsPressed = new AtomicBoolean(false); private static AtomicBoolean shift1Pressed = new AtomicBoolean(false); private static AtomicBoolean shift1Released = new AtomicBoolean(false); private static AtomicBoolean shift2Pressed = new AtomicBoolean(false); @@ -170,6 +178,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA final int keyCode = keyEvent.getKeyCode(); if (keyCode == KeyEvent.VK_SHIFT) { + ourShiftIsPressed.set(event.getID() == KeyEvent.KEY_PRESSED); + if (keyEvent.isControlDown() || keyEvent.isAltDown() || keyEvent.isMetaDown()) { resetState(); return false; @@ -521,7 +531,9 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA private void doNavigate(int index) { final Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(getField().getTextEditor())); - + final Executor executor = ourShiftIsPressed.get() + ? DefaultRunExecutor.getRunExecutorInstance() + : ExecutorRegistry.getInstance().getExecutorById(ToolWindowId.DEBUG); assert project != null; if (isMoreItem(index)) { @@ -569,7 +581,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA return; } } - else if (isActionValue(value) || isSetting(value)) { + else if (isActionValue(value) || isSetting(value) || isRunConfiguration(value)) { focusManager.requestDefaultFocus(true); final Component comp = myContextComponent; final AnActionEvent event = myActionEvent; @@ -580,7 +592,12 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA if (c == null) { c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); } - GotoActionAction.openOptionOrPerformAction(value, pattern, project, c, event); + + if (isRunConfiguration(value)) { + ((ChooseRunConfigurationPopup.ItemWrapper)value).perform(project, executor, DataManager.getInstance().getDataContext(c)); + } else { + GotoActionAction.openOptionOrPerformAction(value, pattern, project, c, event); + } } }); return; @@ -665,6 +682,20 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA myHistoryIndex = 0; myHistoryItem = null; } + + @Override + public void keyPressed(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + myList.repaint(); + } + } + + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_SHIFT) { + myList.repaint(); + } + } }); initSearchField(myPopupField); myPopupField.setOpaque(false); @@ -817,7 +848,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA doNavigate(index); } } - }.registerCustomShortcutSet(CustomShortcutSet.fromString("ENTER"), editor, balloon); + }.registerCustomShortcutSet(CustomShortcutSet.fromString("ENTER", "shift ENTER"), editor, balloon); new DumbAwareAction(){ @Override public void actionPerformed(AnActionEvent e) { @@ -922,7 +953,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA && myProject != null && (((VirtualFile)value).isDirectory() || (file = PsiManager.getInstance(myProject).findFile((VirtualFile)value)) != null)) { - cmp = new GotoFileCellRenderer(Math.min(800, list.getWidth())).getListCellRendererComponent(list, file == null ? value : file, index, isSelected, cellHasFocus); + cmp = new GotoFileCellRenderer(Math.min(800, list.getWidth())) + .getListCellRendererComponent(list, file == null ? value : file, index, isSelected, cellHasFocus); } else if (value instanceof PsiElement) { cmp = myPsiRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); } else { @@ -979,8 +1011,13 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA String name = myClassModel.getElementName(value); assert name != null; append(name); - } - else if (isVirtualFile(value)) { + } else if (value instanceof ChooseRunConfigurationPopup.ItemWrapper) { + final ChooseRunConfigurationPopup.ItemWrapper wrapper = (ChooseRunConfigurationPopup.ItemWrapper)value; + append(wrapper.getText()); + setIcon(wrapper.getIcon()); + setLocationString(ourShiftIsPressed.get() ? "Run" : "Debug"); + myLocationIcon = ourShiftIsPressed.get() ? AllIcons.Toolwindows.ToolWindowRun : AllIcons.Toolwindows.ToolWindowDebugger; + } else if (isVirtualFile(value)) { final VirtualFile file = (VirtualFile)value; if (file instanceof VirtualFilePathWrapper) { append(((VirtualFilePathWrapper)file).getPresentablePath()); @@ -1102,6 +1139,10 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA return o instanceof OptionDescription; } + private static boolean isRunConfiguration(Object o) { + return o instanceof ChooseRunConfigurationPopup.ItemWrapper; + } + private static boolean isVirtualFile(Object o) { return o instanceof VirtualFile; } @@ -1148,12 +1189,23 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA return; } - checkModelsUpToDate(); check(); - buildTopHit(pattern); check(); - buildRecentFiles(pattern); check(); - updatePopup(); check(); - buildToolWindows(pattern); check(); - updatePopup(); check(); + checkModelsUpToDate(); check(); + buildTopHit(pattern); check(); + buildRecentFiles(pattern); check(); + updatePopup(); check(); + buildToolWindows(pattern); check(); + updatePopup(); check(); + + if (!DumbServiceImpl.getInstance(project).isDumb()) { + ApplicationManager.getApplication().runReadAction(new Runnable() { + public void run() { + buildRunConfigurations(pattern); + } + }); + + updatePopup(); + check(); + } if (!DumbServiceImpl.getInstance(project).isDumb()) { ApplicationManager.getApplication().runReadAction(new Runnable() { @@ -1387,6 +1439,86 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA } } + private void buildRunConfigurations(String pattern) { + final List runConfigurations = new ArrayList(); + MinusculeMatcher matcher = new MinusculeMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE); + final ChooseRunConfigurationPopup.ItemWrapper[] wrappers = + ChooseRunConfigurationPopup.createSettingsList(project, new ExecutorProvider() { + @Override + public Executor getExecutor() { + return ExecutorRegistry.getInstance().getExecutorById(ToolWindowId.DEBUG); + } + }, false); + check(); + for (ChooseRunConfigurationPopup.ItemWrapper wrapper : wrappers) { + if (matcher.matches(wrapper.getText())) { + runConfigurations.add(wrapper); + } + check(); + } + + if (runConfigurations.size() > 0) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + if (!myProgressIndicator.isCanceled()) { + myTitleIndexes.runConfigurations = myListModel.size(); + for (Object runConfiguration : runConfigurations) { + myListModel.addElement(runConfiguration); + } + myMoreFilesIndex = runConfigurations.size() >= MAX_RUN_CONFIGURATION ? myListModel.size() - 1 : -1; + } + } + }); + } + + } + + + //private void buildRunConfigurations(String pattern) { + // MinusculeMatcher matcher = new MinusculeMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE); + // RunnerAndConfigurationSettings selected = RunManager.getInstance(project).getSelectedConfiguration(); + // final List runConfigurations = new ArrayList(); + // final RunManagerEx runManager = RunManagerEx.getInstanceEx(project); + // if (selected != null) { + // ExecutionTarget activeTarget = ExecutionTargetManager.getActiveTarget(project); + // for (ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, selected)) { + // if (matcher.matches(eachTarget.getDisplayName())) { + // runConfigurations.add( + // new RunConfigurationsComboBoxAction.SelectTargetAction(project, eachTarget, eachTarget.equals(activeTarget))); + // } + // } + // } + // + // final ConfigurationType[] types = runManager.getConfigurationFactories(); + // for (ConfigurationType type : types) { + // Map> structure = runManager.getStructure(type); + // for (Map.Entry> entry : structure.entrySet()) { + // for (RunnerAndConfigurationSettings settings : entry.getValue()) { + // if (matcher.matches(settings.getName())) { + // runConfigurations.add(new RunConfigurationsComboBoxAction.SelectConfigAction(settings, project)); + // } + // } + // } + // } + // + // if (runConfigurations.size() > 0) { + // UIUtil.invokeLaterIfNeeded(new Runnable() { + // @Override + // public void run() { + // if (!myProgressIndicator.isCanceled()) { + // myTitleIndexes.runConfigurations = myListModel.size(); + // for (Object runConfiguration : runConfigurations) { + // myListModel.addElement(runConfiguration); + // } + // myMoreFilesIndex = runConfigurations.size() >= MAX_RUN_CONFIGURATION ? myListModel.size() - 1 : -1; + // } + // } + // }); + // } + // + //} + private void buildClasses(String pattern, boolean includeLibraries) { if (pattern.indexOf('.') != -1) { //todo[kb] it's not a mistake. If we search for "*.png" or "index.xml" in SearchEverywhere @@ -1402,6 +1534,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA List matches = collectResults(pattern, includeLibs ? myClassModel.getNames(true) : myClasses, myClassModel); // FindSymbolParameters parameters = FindSymbolParameters.wrap(pattern, project, includeLibs); final List classes = new ArrayList(); + check(); for (MatchResult matchResult : matches) { if (clsCounter > maxCount) break; @@ -1507,6 +1640,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA myAlreadyAddedActions.add(action); } break; + case RUN_CONFIGURATION: + break; } } } @@ -1828,6 +1963,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA static class TitleIndexes { int topHit; int recentFiles; + int runConfigurations; int classes; int files; int actions; @@ -1840,6 +1976,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA final String gotoActionTitle; final String gotoSettingsTitle; final String gotoRecentFilesTitle; + final String gotoRunConfigurationsTitle; final String gotoSymbolTitle; static final String toolWindowsTitle = "Tool Windows"; @@ -1855,12 +1992,18 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA String gotoRecentFiles = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("RecentFiles")); gotoRecentFilesTitle = StringUtil.isEmpty(gotoRecentFiles) ? "Recent Files" : "Recent Files (" + gotoRecentFiles + ")"; String gotoSymbol = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("GotoSymbol")); - gotoSymbolTitle = StringUtil.isEmpty(gotoClass) ? "Symbols" : "Symbols (" + gotoSymbol + ")"; + gotoSymbolTitle = StringUtil.isEmpty(gotoSymbol) ? "Symbols" : "Symbols (" + gotoSymbol + ")"; + String gotoRunConfiguration = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ChooseDebugConfiguration")); + if (StringUtil.isEmpty(gotoRunConfiguration)) { + gotoRunConfiguration = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ChooseRunConfiguration")); + } + gotoRunConfigurationsTitle = StringUtil.isEmpty(gotoRunConfiguration) ? "Run Configurations" : "Run Configurations (" + gotoRunConfiguration + ")"; } String getTitle(int index) { if (index == topHit) return index == 0 ? "Top Hit" : "Top Hits"; if (index == recentFiles) return gotoRecentFilesTitle; + if (index == runConfigurations) return gotoRunConfigurationsTitle; if (index == classes) return gotoClassTitle; if (index == files) return gotoFileTitle; if (index == toolWindows) return toolWindowsTitle; @@ -1871,7 +2014,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA } int next(int index) { - int[] all = new int[]{topHit, recentFiles, classes, files, actions, settings, toolWindows, symbols}; + int[] all = new int[]{topHit, recentFiles, runConfigurations, classes, files, actions, settings, toolWindows, symbols}; Arrays.sort(all); for (int next : all) { if (next > index) return next; @@ -1880,7 +2023,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA } int prev(int index) { - int[] all = new int[]{topHit, recentFiles, classes, files, actions, settings, toolWindows, symbols}; + int[] all = new int[]{topHit, recentFiles, runConfigurations, classes, files, actions, settings, toolWindows, symbols}; Arrays.sort(all); for (int i = all.length-1; i >= 0; i--) { if (all[i] != -1 && all[i] < index) return all[i]; @@ -1891,6 +2034,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA public void clear() { topHit = -1; + runConfigurations = -1; recentFiles = -1; classes = -1; files = -1; @@ -1960,7 +2104,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA return result; } - private enum HistoryType {CLASS, FILE, SYMBOL, SETTING, ACTION} + private enum HistoryType {CLASS, FILE, SYMBOL, SETTING, ACTION, RUN_CONFIGURATION} @Nullable private static HistoryType parseHistoryType(@Nullable String name) { From e6806dd3b309db52856dc274c32468cffd550c6b Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 10 Mar 2014 16:02:09 +0100 Subject: [PATCH 06/32] remove old code commented code --- .../RunConfigurationsComboBoxAction.java | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java b/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java index 7cb6089d963d..d9b226066f0b 100644 --- a/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java +++ b/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -198,25 +198,6 @@ public class RunConfigurationsComboBoxAction extends ComboBoxAction implements D } } - //final RunnerAndConfigurationSettings[] configurations = runManager.getConfigurationSettingsList(type); - //ArrayList configurationSettingsList = new ArrayList(); - //int i = 0; - //for (RunnerAndConfigurationSettings configuration : configurations) { - // if (configuration.isTemporary()) { - // configurationSettingsList.add(configuration); - // } - // else { - // configurationSettingsList.add(i++, configuration); - // } - //} - //for (final RunnerAndConfigurationSettings configuration : configurationSettingsList) { - // //if (runManager.canRunConfiguration(configuration)) { - // final SelectConfigAction action = new SelectConfigAction(configuration, project); - // - // actionGroup.add(action); - // //} - //} - allActionsGroup.add(actionGroup); allActionsGroup.addSeparator(); } From f60abae9d540ccdf435de888e630712574862fdb Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Mon, 10 Mar 2014 16:03:07 +0100 Subject: [PATCH 07/32] NPE protection --- .../execution/actions/RunConfigurationsComboBoxAction.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java b/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java index d9b226066f0b..0453a5401cbf 100644 --- a/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java +++ b/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java @@ -300,7 +300,10 @@ public class RunConfigurationsComboBoxAction extends ComboBoxAction implements D } final Presentation presentation = getTemplatePresentation(); presentation.setText(name, false); - presentation.setDescription("Select " + configuration.getType().getConfigurationTypeDescription() + " '" + name + "'"); + final ConfigurationType type = configuration.getType(); + if (type != null) { + presentation.setDescription("Select " + type.getConfigurationTypeDescription() + " '" + name + "'"); + } updateIcon(presentation); } From 799041b776892f25ab9bb28a8ef71e6cb428892c Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 7 Mar 2014 14:08:00 +0400 Subject: [PATCH 08/32] notnull --- .../intellij/openapi/project/DumbService.java | 16 ++++++++-------- .../src/com/intellij/mock/MockDumbService.java | 6 +++--- .../execution/filters/CompositeFilterTest.java | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/project/DumbService.java b/platform/core-api/src/com/intellij/openapi/project/DumbService.java index 4bced97e584a..3fa4bbb49f46 100644 --- a/platform/core-api/src/com/intellij/openapi/project/DumbService.java +++ b/platform/core-api/src/com/intellij/openapi/project/DumbService.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -55,7 +55,7 @@ public abstract class DumbService { */ public abstract boolean isDumb(); - public static boolean isDumb(Project project) { + public static boolean isDumb(@NotNull Project project) { return getInstance(project).isDumb(); } @@ -63,7 +63,7 @@ public abstract class DumbService { * Executes the runnable immediately if not in dumb mode, or on AWT Event Dispatch thread when the dumb mode ends. * @param runnable runnable to run */ - public abstract void runWhenSmart(Runnable runnable); + public abstract void runWhenSmart(@NotNull Runnable runnable); /** * Pause the current thread until dumb mode ends and then continue execution. @@ -75,7 +75,7 @@ public abstract class DumbService { /** * Pause the current thread until dumb mode ends, and then run the read action. Index is guaranteed to be available inside that read action. */ - public T runReadActionInSmartMode(final Computable r) { + public T runReadActionInSmartMode(@NotNull final Computable r) { final Ref result = new Ref(); runReadActionInSmartMode(new Runnable() { @Override @@ -105,7 +105,7 @@ public abstract class DumbService { /** * Pause the current thread until dumb mode ends, and then run the read action. Index is guaranteed to be available inside that read action. */ - public void runReadActionInSmartMode(final Runnable r) { + public void runReadActionInSmartMode(@NotNull final Runnable r) { while (true) { waitForSmartMode(); boolean success = ApplicationManager.getApplication().runReadAction(new Computable() { @@ -130,7 +130,7 @@ public abstract class DumbService { * * @see #runReadActionInSmartMode(Runnable) */ - public void repeatUntilPassesInSmartMode(final Runnable r) { + public void repeatUntilPassesInSmartMode(@NotNull final Runnable r) { while (true) { waitForSmartMode(); try { @@ -156,7 +156,7 @@ public abstract class DumbService { }); } - public void smartInvokeLater(@NotNull final Runnable runnable, ModalityState modalityState) { + public void smartInvokeLater(@NotNull final Runnable runnable, @NotNull ModalityState modalityState) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { @@ -207,7 +207,7 @@ public abstract class DumbService { }); } - public abstract void showDumbModeNotification(String message); + public abstract void showDumbModeNotification(@NotNull String message); public abstract Project getProject(); diff --git a/platform/core-impl/src/com/intellij/mock/MockDumbService.java b/platform/core-impl/src/com/intellij/mock/MockDumbService.java index 51b3ed0825c6..33c39d130254 100644 --- a/platform/core-impl/src/com/intellij/mock/MockDumbService.java +++ b/platform/core-impl/src/com/intellij/mock/MockDumbService.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ public class MockDumbService extends DumbService { } @Override - public void runWhenSmart(Runnable runnable) { + public void runWhenSmart(@NotNull Runnable runnable) { runnable.run(); } @@ -52,7 +52,7 @@ public class MockDumbService extends DumbService { } @Override - public void showDumbModeNotification(String message) { + public void showDumbModeNotification(@NotNull String message) { throw new UnsupportedOperationException(); } diff --git a/platform/lang-api/testSources/com/intellij/execution/filters/CompositeFilterTest.java b/platform/lang-api/testSources/com/intellij/execution/filters/CompositeFilterTest.java index 2582f93637fb..004ca62f74ce 100644 --- a/platform/lang-api/testSources/com/intellij/execution/filters/CompositeFilterTest.java +++ b/platform/lang-api/testSources/com/intellij/execution/filters/CompositeFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ public class CompositeFilterTest { } @Override - public void runWhenSmart(Runnable runnable) { + public void runWhenSmart(@NotNull Runnable runnable) { } @Override @@ -53,7 +53,7 @@ public class CompositeFilterTest { } @Override - public void showDumbModeNotification(String message) { + public void showDumbModeNotification(@NotNull String message) { } @Override From cce38ff4094bd7959387596d2891cf61da61a688 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 7 Mar 2014 19:37:45 +0400 Subject: [PATCH 09/32] cleanup --- .../psi/impl/source/PsiClassImpl.java | 21 +++++++++---------- .../editor/colors/TextAttributesKey.java | 9 +++++--- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java index 5edd337f5113..d7ba848980de 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -494,20 +494,19 @@ public class PsiClassImpl extends JavaStubPsiElement> implements @Override public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) { if (isEnum()) { - String name = getName(); - if (name != null) { + String myName = getName(); + if (myName != null) { try { final NameHint nameHint = processor.getHint(NameHint.KEY); final ElementClassHint classHint = processor.getHint(ElementClassHint.KEY); - if (nameHint == null || VALUES_METHOD.equals(nameHint.getName(state))) { - if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) { - if (!processor.execute(getValuesMethod(), ResolveState.initial())) return false; - } + String nameToSearch = nameHint == null ? null : nameHint.getName(state); + if (VALUES_METHOD.equals(nameToSearch) && + (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD))) { + if (!processor.execute(getValuesMethod(), ResolveState.initial())) return false; } - if (nameHint == null || VALUE_OF_METHOD.equals(nameHint.getName(state))) { - if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) { - if (!processor.execute(getValueOfMethod(), ResolveState.initial())) return false; - } + if (VALUE_OF_METHOD.equals(nameToSearch) && + (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD))) { + if (!processor.execute(getValueOfMethod(), ResolveState.initial())) return false; } } catch (IncorrectOperationException e) { diff --git a/platform/core-api/src/com/intellij/openapi/editor/colors/TextAttributesKey.java b/platform/core-api/src/com/intellij/openapi/editor/colors/TextAttributesKey.java index 542580662556..807ee6102b7f 100644 --- a/platform/core-api/src/com/intellij/openapi/editor/colors/TextAttributesKey.java +++ b/platform/core-api/src/com/intellij/openapi/editor/colors/TextAttributesKey.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,19 +18,22 @@ package com.intellij.openapi.editor.colors; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.*; +import com.intellij.util.ConcurrencyUtil; import com.intellij.util.containers.ConcurrentHashMap; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.concurrent.ConcurrentMap; + /** * A type of item with a distinct highlighting in an editor or in other views. */ public final class TextAttributesKey implements Comparable { private static final TextAttributes NULL_ATTRIBUTES = new TextAttributes(); - private static final ConcurrentHashMap ourRegistry = new ConcurrentHashMap(); + private static final ConcurrentMap ourRegistry = new ConcurrentHashMap(); private static final NullableLazyValue ourDefaultsProvider = new VolatileNullableLazyValue() { @Nullable @Override @@ -58,7 +61,7 @@ public final class TextAttributesKey implements Comparable { @NotNull public static TextAttributesKey find(@NotNull @NonNls String externalName) { - return ourRegistry.cacheOrGet(externalName, new TextAttributesKey(externalName)); + return ConcurrencyUtil.cacheOrGet(ourRegistry, externalName, new TextAttributesKey(externalName)); } public String toString() { From 35a1ebacee6945734d37ee37c5e9852b34a5cb41 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 10 Mar 2014 18:51:47 +0400 Subject: [PATCH 10/32] optimisation: use AtomicLazyNullableValue to avoid extra indirection and save memory --- .../psi/impl/compiled/ClsTypeElementImpl.java | 36 +++++++--------- .../openapi/util/AtomicNullableLazyValue.java | 43 +++++++++++++++++++ 2 files changed, 59 insertions(+), 20 deletions(-) create mode 100644 platform/util/src/com/intellij/openapi/util/AtomicNullableLazyValue.java diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java index 16d971238684..9d4e3888771c 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeElementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,8 @@ package com.intellij.psi.impl.compiled; import com.intellij.openapi.util.AtomicNotNullLazyValue; +import com.intellij.openapi.util.AtomicNullableLazyValue; import com.intellij.openapi.util.NotNullLazyValue; -import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.PsiJavaParserFacadeImpl; @@ -39,18 +39,17 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement private final PsiElement myParent; private final String myTypeText; private final char myVariance; - private final NotNullLazyValue> myChild; + private final AtomicNullableLazyValue myChild; private final NotNullLazyValue myCachedType; public ClsTypeElementImpl(@NotNull PsiElement parent, @NotNull String typeText, char variance) { myParent = parent; myTypeText = TypeInfo.internFrequentType(typeText); myVariance = variance; - myChild = new AtomicNotNullLazyValue>() { - @NotNull + myChild = new AtomicNullableLazyValue() { @Override - protected Ref compute() { - return Ref.create(calculateChild()); + protected ClsElementImpl compute() { + return calculateChild(); } }; myCachedType = new AtomicNotNullLazyValue() { @@ -65,7 +64,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement @Override @NotNull public PsiElement[] getChildren() { - ClsElementImpl child = myChild.getValue().get(); + ClsElementImpl child = myChild.getValue(); return child != null ? new PsiElement[]{child} : PsiElement.EMPTY_ARRAY; } @@ -109,7 +108,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException { setMirrorCheckingType(element, JavaElementType.TYPE); - ClsElementImpl child = myChild.getValue().get(); + ClsElementImpl child = myChild.getValue(); if (child != null) { child.setMirror(element.getFirstChildNode()); } @@ -138,24 +137,23 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement if (PsiJavaParserFacadeImpl.getPrimitiveType(myTypeText) != null) { return null; } - else if (isArray()) { + if (isArray()) { return myVariance == VARIANCE_NONE ? new ClsTypeElementImpl(this, myTypeText.substring(0, myTypeText.length() - 2), myVariance) : new ClsTypeElementImpl(this, myTypeText, VARIANCE_NONE); } - else if (isVarArgs()) { + if (isVarArgs()) { return new ClsTypeElementImpl(this, myTypeText.substring(0, myTypeText.length() - 3), myVariance); } - else { - return myVariance != VARIANCE_INVARIANT ? new ClsJavaCodeReferenceElementImpl(this, myTypeText) : null; - } + return myVariance == VARIANCE_INVARIANT ? null : new ClsJavaCodeReferenceElementImpl(this, myTypeText); } + @NotNull private PsiType calculateType() { PsiType result = PsiJavaParserFacadeImpl.getPrimitiveType(myTypeText); if (result != null) return result; - ClsElementImpl childElement = myChild.getValue().get(); + ClsElementImpl childElement = myChild.getValue(); if (childElement instanceof ClsTypeElementImpl) { if (isArray()) { switch (myVariance) { @@ -175,7 +173,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement return new PsiEllipsisType(((PsiTypeElement)childElement).getType()); } } - else if (childElement instanceof ClsJavaCodeReferenceElementImpl) { + if (childElement instanceof ClsJavaCodeReferenceElementImpl) { PsiClassReferenceType psiClassReferenceType = new PsiClassReferenceType((PsiJavaCodeReferenceElement)childElement, null); switch (myVariance) { case VARIANCE_NONE: @@ -191,10 +189,8 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement return null; } } - else { - assert childElement == null : this; - return PsiWildcardType.createUnbounded(getManager()); - } + assert childElement == null : this; + return PsiWildcardType.createUnbounded(getManager()); } @Override diff --git a/platform/util/src/com/intellij/openapi/util/AtomicNullableLazyValue.java b/platform/util/src/com/intellij/openapi/util/AtomicNullableLazyValue.java new file mode 100644 index 000000000000..cc9c89463139 --- /dev/null +++ b/platform/util/src/com/intellij/openapi/util/AtomicNullableLazyValue.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.intellij.openapi.util; + +/** + * @author peter + */ +public abstract class AtomicNullableLazyValue extends NullableLazyValue { + private volatile T myValue; + private volatile boolean myComputed; + + @Override + public final T getValue() { + boolean computed = myComputed; + T value = myValue; + if (computed) { + return value; + } + synchronized (this) { + computed = myComputed; + value = myValue; + if (!computed) { + myValue = value = compute(); + myComputed = true; + } + } + return value; + } +} From 1052ef222a6917061ab3e5d74c254293b3701939 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 10 Mar 2014 18:54:37 +0400 Subject: [PATCH 11/32] less garbage --- .../src/com/intellij/psi/impl/source/PsiClassReferenceType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java index f304fe250bae..361f2374b904 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassReferenceType.java @@ -139,7 +139,7 @@ public class PsiClassReferenceType extends PsiClassType.Stub { public ClassResolveResult resolveGenerics() { PsiUtilCore.ensureValid(myReference); final JavaResolveResult result = myReference.advancedResolve(false); - return new DelegatingClassResolveResult(result); + return result.getElement() == null ? ClassResolveResult.EMPTY : new DelegatingClassResolveResult(result); } @Override From 8e482449cf77958ce201f0f29513e479df148cd4 Mon Sep 17 00:00:00 2001 From: Michael Golubev Date: Mon, 10 Mar 2014 16:33:10 +0100 Subject: [PATCH 12/32] IDEA-119822 - Support Heroku Debug --- .../debug/JavaDebuggerLauncherImpl.java | 22 ++++++++++++++- .../debug/JavaDebugConnectionData.java | 6 ++++ .../debug/JavaDebugServerModeHandler.java | 28 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugServerModeHandler.java diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/debug/JavaDebuggerLauncherImpl.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/debug/JavaDebuggerLauncherImpl.java index 76658698d034..9fb0d3f81e3c 100644 --- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/debug/JavaDebuggerLauncherImpl.java +++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/deployment/debug/JavaDebuggerLauncherImpl.java @@ -2,6 +2,9 @@ package com.intellij.remoteServer.impl.runtime.deployment.debug; import com.intellij.debugger.DebugEnvironment; import com.intellij.debugger.DebugUIEnvironment; +import com.intellij.debugger.DebuggerManager; +import com.intellij.debugger.engine.DebugProcess; +import com.intellij.debugger.engine.DebugProcessAdapter; import com.intellij.debugger.engine.RemoteDebugProcessHandler; import com.intellij.debugger.ui.DebuggerPanelsManager; import com.intellij.diagnostic.logging.LogFilesManager; @@ -21,6 +24,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.remoteServer.configuration.RemoteServer; import com.intellij.remoteServer.runtime.deployment.debug.JavaDebugConnectionData; +import com.intellij.remoteServer.runtime.deployment.debug.JavaDebugServerModeHandler; import com.intellij.remoteServer.runtime.deployment.debug.JavaDebuggerLauncher; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,7 +43,9 @@ public class JavaDebuggerLauncherImpl extends JavaDebuggerLauncher { final Project project = executionEnvironment.getProject(); Executor executor = DefaultDebugExecutor.getDebugExecutorInstance(); final DebuggerPanelsManager manager = DebuggerPanelsManager.getInstance(project); - final RemoteConnection remoteConnection = new RemoteConnection(true, info.getHost(), String.valueOf(info.getPort()), false); + final JavaDebugServerModeHandler serverModeHandler = info.getServerModeHandler(); + boolean serverMode = serverModeHandler != null; + final RemoteConnection remoteConnection = new RemoteConnection(true, info.getHost(), String.valueOf(info.getPort()), serverMode); DebugEnvironment debugEnvironment = new RemoteServerDebugEnvironment(project, remoteConnection, executionEnvironment.getRunProfile()); DebugUIEnvironment debugUIEnvironment = new RemoteServerDebugUIEnvironment(debugEnvironment, executionEnvironment); RunContentDescriptor debugContentDescriptor = manager.attachVirtualMachine(debugUIEnvironment); @@ -49,6 +55,20 @@ public class JavaDebuggerLauncherImpl extends JavaDebuggerLauncher { processHandler.startNotify(); ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, debugContentDescriptor, executionEnvironment.getContentToReuse()); + if (serverMode) { + serverModeHandler.attachRemote(); + DebuggerManager.getInstance(executionEnvironment.getProject()) + .addDebugProcessListener(processHandler, new DebugProcessAdapter() { + public void processDetached(DebugProcess process, boolean closedByUser) { + try { + serverModeHandler.detachRemote(); + } + catch (ExecutionException e) { + LOG.info(e); + } + } + }); + } } private static class RemoteServerDebugUIEnvironment implements DebugUIEnvironment { diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugConnectionData.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugConnectionData.java index e5d63a8d167b..b4efb94c6e14 100644 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugConnectionData.java +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugConnectionData.java @@ -1,6 +1,7 @@ package com.intellij.remoteServer.runtime.deployment.debug; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author nik @@ -22,4 +23,9 @@ public class JavaDebugConnectionData implements DebugConnectionData { public int getPort() { return myPort; } + + @Nullable + public JavaDebugServerModeHandler getServerModeHandler() { + return null; + } } diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugServerModeHandler.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugServerModeHandler.java new file mode 100644 index 000000000000..68399461e77c --- /dev/null +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/debug/JavaDebugServerModeHandler.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.remoteServer.runtime.deployment.debug; + +import com.intellij.execution.ExecutionException; + +/** + * @author michael.golubev + */ +public interface JavaDebugServerModeHandler { + + void attachRemote() throws ExecutionException; + + void detachRemote() throws ExecutionException; +} From 61e2ecc53ceaa7b31394bfc3a380172619f32cec Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 10 Mar 2014 16:34:44 +0100 Subject: [PATCH 13/32] =?UTF-8?q?renderValue=20=E2=80=94=20add=20XValue=20?= =?UTF-8?q?parameter=20to=20simplify,=20why=20we=20need=20to=20create?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit old renderValue(XValueTextRenderer) is not deprecated, wait review. --- .../xdebugger/frame/presentation/XValuePresentation.java | 5 +++++ .../xdebugger/impl/evaluate/quick/XValueHint.java | 2 +- .../xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java | 8 ++++---- .../impl/ui/tree/nodes/XValuePresentationUtil.java | 5 +++-- .../com/intellij/xdebugger/XDebuggerTestUtil.java | 2 +- .../testSrc/com/intellij/xdebugger/XTestValueNode.java | 9 ++++++++- 6 files changed, 22 insertions(+), 9 deletions(-) diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/presentation/XValuePresentation.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/presentation/XValuePresentation.java index 5467033f4e32..ef8c30aa9397 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/presentation/XValuePresentation.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/presentation/XValuePresentation.java @@ -16,6 +16,7 @@ package com.intellij.xdebugger.frame.presentation; import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.xdebugger.frame.XValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,6 +36,10 @@ public abstract class XValuePresentation { */ public abstract void renderValue(@NotNull XValueTextRenderer renderer); + public void renderValue(@NotNull XValue value, @NotNull XValueTextRenderer renderer) { + renderValue(renderer); + } + /** * @return separator between name and value in a debugger tree */ diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java index ebf5d69a166e..d4fc68bb4cbd 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java @@ -113,7 +113,7 @@ public class XValueHint extends AbstractValueHint { SimpleColoredText text = new SimpleColoredText(); text.append(myExpression, XDebuggerUIConstants.VALUE_NAME_ATTRIBUTES); - XValueNodeImpl.buildText(valuePresenter, text); + XValueNodeImpl.buildText(result, valuePresenter, text); if (!hasChildren) { SimpleColoredComponent component = HintUtil.createInformationComponent(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java index 8b679f120739..d691e64bc662 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java @@ -111,7 +111,7 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu public void applyPresentation(@Nullable Icon icon, @NotNull XValuePresentation valuePresentation, boolean hasChildren) { setIcon(icon); myValuePresentation = valuePresentation; - myRawValue = XValuePresentationUtil.computeValueText(valuePresentation); + myRawValue = XValuePresentationUtil.computeValueText(myValueContainer, valuePresentation); updateText(); setLeaf(!hasChildren); @@ -140,7 +140,7 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu } } appendName(); - buildText(myValuePresentation, myText); + buildText(myValueContainer, myValuePresentation, myText); } private void appendName() { @@ -150,13 +150,13 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu } } - public static void buildText(@NotNull XValuePresentation valuePresenter, @NotNull final ColoredTextContainer text) { + public static void buildText(@NotNull XValue value, @NotNull XValuePresentation valuePresenter, @NotNull ColoredTextContainer text) { XValuePresentationUtil.appendSeparator(text, valuePresenter.getSeparator()); String type = valuePresenter.getType(); if (type != null) { text.append("{" + type + "} ", XDebuggerUIConstants.TYPE_ATTRIBUTES); } - valuePresenter.renderValue(new XValueTextRendererImpl(text)); + valuePresenter.renderValue(value, new XValueTextRendererImpl(text)); } @Override diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValuePresentationUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValuePresentationUtil.java index aaad5a9827c2..b55cfb68b0fc 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValuePresentationUtil.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValuePresentationUtil.java @@ -22,6 +22,7 @@ import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.ui.ColoredTextContainer; import com.intellij.ui.JBColor; import com.intellij.ui.SimpleTextAttributes; +import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.frame.presentation.XValuePresentation; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -86,9 +87,9 @@ public class XValuePresentationUtil { } @NotNull - public static String computeValueText(@NotNull XValuePresentation presentation) { + public static String computeValueText(@NotNull XValue value, @NotNull XValuePresentation presentation) { XValuePresentationTextExtractor extractor = new XValuePresentationTextExtractor(); - presentation.renderValue(extractor); + presentation.renderValue(value, extractor); return extractor.getText(); } diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java index 0f140e38f893..253123b748a6 100644 --- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java @@ -172,7 +172,7 @@ public class XDebuggerTestUtil { } public static XTestValueNode computePresentation(XValue value, long timeout) throws InterruptedException { - XTestValueNode node = new XTestValueNode(); + XTestValueNode node = new XTestValueNode(value); if (value instanceof com.intellij.xdebugger.frame.XNamedValue) { node.myName = ((XNamedValue)value).getName(); } diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java index 83ed493a403b..02019692207b 100644 --- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java +++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XTestValueNode.java @@ -1,6 +1,7 @@ package com.intellij.xdebugger; import com.intellij.xdebugger.frame.XFullValueEvaluator; +import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.frame.presentation.XValuePresentation; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodePresentationConfigurator; import com.intellij.xdebugger.impl.ui.tree.nodes.XValuePresentationUtil; @@ -20,12 +21,18 @@ public class XTestValueNode extends XValueNodePresentationConfigurator.Configura private final Semaphore myFinished = new Semaphore(0); + private final XValue myXValue; + + public XTestValueNode(@NotNull XValue value) { + myXValue = value; + } + @Override public void applyPresentation(@Nullable Icon icon, @NotNull XValuePresentation valuePresentation, boolean hasChildren) { myType = valuePresentation.getType(); - myValue = XValuePresentationUtil.computeValueText(valuePresentation); + myValue = XValuePresentationUtil.computeValueText(myXValue, valuePresentation); myHasChildren = hasChildren; myFinished.release(); From 0bca3c69d17aecc568b578b054b6ac946d9eb997 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 9 Mar 2014 14:41:46 +0400 Subject: [PATCH 14/32] [log] Remove obsolete CommitCell & its Renderer --- .../vcs/log/graph/render/CommitCell.java | 29 ------------------- .../vcs/log/graph/render/GraphCommitCell.java | 20 +++++++++---- .../vcs/log/ui/frame/VcsLogGraphTable.java | 3 -- .../ui/render/AbstractPaddingCellRender.java | 12 ++++---- .../vcs/log/ui/render/CommitCellRender.java | 21 -------------- 5 files changed, 21 insertions(+), 64 deletions(-) delete mode 100644 platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/CommitCell.java delete mode 100644 platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/CommitCellRender.java diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/CommitCell.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/CommitCell.java deleted file mode 100644 index f8bade5a746c..000000000000 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/CommitCell.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.intellij.vcs.log.graph.render; - -import com.intellij.vcs.log.VcsRef; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; - -/** - * @author erokhins - */ -public class CommitCell { - - private final String text; - private final Collection refsToThisCommit; - - public CommitCell(@NotNull String text, @NotNull Collection refsToThisCommit) { - this.text = text; - this.refsToThisCommit = refsToThisCommit; - } - - public String getText() { - return text; - } - - public Collection getRefsToThisCommit() { - return refsToThisCommit; - } - -} diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/GraphCommitCell.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/GraphCommitCell.java index f09ceb6ff3b2..c7651216fcb1 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/GraphCommitCell.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/render/GraphCommitCell.java @@ -5,14 +5,24 @@ import org.jetbrains.annotations.NotNull; import java.util.Collection; +public class GraphCommitCell { -/** - * @author erokhins - */ -public class GraphCommitCell extends CommitCell { + @NotNull private final String myText; + @NotNull private final Collection myRefsToThisCommit; public GraphCommitCell(@NotNull String text, @NotNull Collection refsToThisCommit) { - super(text, refsToThisCommit); + myText = text; + myRefsToThisCommit = refsToThisCommit; + } + + @NotNull + public String getText() { + return myText; + } + + @NotNull + public Collection getRefsToThisCommit() { + return myRefsToThisCommit; } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index 2423dacb1fc5..bc7e81e319dc 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -19,11 +19,9 @@ import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.graph.*; -import com.intellij.vcs.log.graph.render.CommitCell; import com.intellij.vcs.log.graph.render.GraphCommitCell; import com.intellij.vcs.log.graph.render.PositionUtil; import com.intellij.vcs.log.ui.VcsLogUI; -import com.intellij.vcs.log.ui.render.CommitCellRender; import com.intellij.vcs.log.ui.render.GraphCommitCellRender; import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel; import org.jetbrains.annotations.NotNull; @@ -68,7 +66,6 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C setDefaultRenderer(VirtualFile.class, new RootCellRenderer(myUI)); setDefaultRenderer(GraphCommitCell.class, myGraphCommitCellRender); - setDefaultRenderer(CommitCell.class, new CommitCellRender(myUI.getColorManager(), logDataHolder)); setDefaultRenderer(String.class, new StringCellRenderer()); setRowHeight(HEIGHT_CELL); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/AbstractPaddingCellRender.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/AbstractPaddingCellRender.java index b988ccd93edc..e802a2ecbb6e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/AbstractPaddingCellRender.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/AbstractPaddingCellRender.java @@ -10,7 +10,7 @@ import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.VcsRef; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.graph.PaintInfo; -import com.intellij.vcs.log.graph.render.CommitCell; +import com.intellij.vcs.log.graph.render.GraphCommitCell; import com.intellij.vcs.log.ui.VcsLogColorManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -49,7 +49,7 @@ public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer return; } - CommitCell cell = getAssertCommitCell(value); + GraphCommitCell cell = getAssertCommitCell(value); myGraphImage = getGraphImage(row); myRefs = cell.getRefsToThisCommit(); @@ -82,14 +82,14 @@ public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer if (myGraphImage != null) { UIUtil.drawImage(g, myGraphImage.getImage(), 0, 0, null); } - else if (this instanceof GraphCommitCellRender) { // TODO temporary diagnostics: why does graph sometimes disappear + else { // TODO temporary diagnostics: why does graph sometimes disappear LOG.error("Image is null"); } } - private static CommitCell getAssertCommitCell(Object value) { - assert value instanceof CommitCell : "Value of incorrect class was supplied: " + value; - return (CommitCell)value; + private static GraphCommitCell getAssertCommitCell(Object value) { + assert value instanceof GraphCommitCell : "Value of incorrect class was supplied: " + value; + return (GraphCommitCell)value; } protected void drawRefs(@NotNull Graphics2D g2, @NotNull Collection refs, int padding) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/CommitCellRender.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/CommitCellRender.java deleted file mode 100644 index cb9040bc6e22..000000000000 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/CommitCellRender.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.intellij.vcs.log.ui.render; - -import com.intellij.vcs.log.data.VcsLogDataHolder; -import com.intellij.vcs.log.graph.PaintInfo; -import com.intellij.vcs.log.ui.VcsLogColorManager; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class CommitCellRender extends AbstractPaddingCellRender { - - public CommitCellRender(@NotNull VcsLogColorManager colorManager, @NotNull VcsLogDataHolder dataHolder) { - super(colorManager, dataHolder); - } - - @Nullable - @Override - protected PaintInfo getGraphImage(int row) { - return null; - } - -} From 55c79a04fecdcfc320fc48159e302eeebe9b9dc1 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 9 Mar 2014 14:46:36 +0400 Subject: [PATCH 15/32] [log] Make it possible to add VcsLogHighlighters to the log table. --- .../intellij/vcs/log/VcsLogHighlighter.java | 35 +++++++++++++++++++ .../src/com/intellij/vcs/log/ui/VcsLogUI.java | 14 +++++--- .../vcs/log/ui/frame/VcsLogGraphTable.java | 29 ++++++++++++++- .../ui/render/AbstractPaddingCellRender.java | 7 +++- .../log/ui/render/GraphCommitCellRender.java | 7 ++-- 5 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogHighlighter.java diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogHighlighter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogHighlighter.java new file mode 100644 index 000000000000..9fba0eca62a0 --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogHighlighter.java @@ -0,0 +1,35 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.vcs.log; + +import org.jetbrains.annotations.Nullable; + +import java.awt.*; + +/** + * Allows to add some highlighting to the Vcs Log table entries. + */ +public interface VcsLogHighlighter { + + /** + * Return the color which should be used for the log table entries foreground, or null if default color should be used. + * @param commitIndex index of commit (can be transferred to the Hash and vice versa). + * @param isSelected if true, the row currently has selection on it. + */ + @Nullable + Color getForeground(int commitIndex, boolean isSelected); + +} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java index 15b0dfd75332..02595cf95c7a 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java @@ -9,10 +9,7 @@ import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.util.PairFunction; import com.intellij.util.ui.UIUtil; -import com.intellij.vcs.log.Hash; -import com.intellij.vcs.log.VcsLog; -import com.intellij.vcs.log.VcsLogFilterCollection; -import com.intellij.vcs.log.VcsLogSettings; +import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.*; import com.intellij.vcs.log.graph.*; import com.intellij.vcs.log.impl.VcsLogImpl; @@ -343,4 +340,13 @@ public class VcsLogUI { ApplicationManager.getApplication().assertIsDispatchThread(); return myDataPack; } + + public void addHighlighter(@NotNull VcsLogHighlighter highlighter) { + getTable().addHighlighter(highlighter); + } + + public void removeHighlighter(@NotNull VcsLogHighlighter highlighter) { + getTable().removeHighlighter(highlighter); + } + } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index bc7e81e319dc..4aab76c67bd9 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -16,6 +16,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.DateFormatUtil; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.VcsLogHighlighter; import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.graph.*; @@ -35,6 +36,7 @@ import java.awt.*; import java.awt.datatransfer.StringSelection; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; @@ -55,6 +57,8 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C private boolean myColumnsSizeInitialized = false; private volatile boolean myRepaintFreezed; + @NotNull private final Collection myHighlighters = ContainerUtil.newArrayList(); + @NotNull private DataPack myDataPack; public VcsLogGraphTable(@NotNull VcsLogUI UI, @NotNull final VcsLogDataHolder logDataHolder, @NotNull DataPack initialDataPack) { @@ -62,7 +66,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C myUI = UI; myLogDataHolder = logDataHolder; myDataPack = initialDataPack; - myGraphCommitCellRender = new GraphCommitCellRender(myUI.getColorManager(), logDataHolder, myDataPack.getGraphFacade()); + myGraphCommitCellRender = new GraphCommitCellRender(myUI.getColorManager(), logDataHolder, myDataPack.getGraphFacade(), this); setDefaultRenderer(VirtualFile.class, new RootCellRenderer(myUI)); setDefaultRenderer(GraphCommitCell.class, myGraphCommitCellRender); @@ -240,6 +244,28 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C myGraphCommitCellRender.updateGraphFacade(dataPack.getGraphFacade()); } + public void addHighlighter(@NotNull VcsLogHighlighter highlighter) { + myHighlighters.add(highlighter); + } + + public void removeHighlighter(@NotNull VcsLogHighlighter highlighter) { + myHighlighters.remove(highlighter); + } + + public void applyHighlighters(@NotNull Component rendererComponent, int row, boolean selected) { + boolean fgUpdated = false; + for (VcsLogHighlighter highlighter : myHighlighters) { + Color color = highlighter.getForeground(myDataPack.getGraphFacade().getCommitAtRow(row), selected); + if (color != null) { + rendererComponent.setForeground(color); + fgUpdated = true; + } + } + if (!fgUpdated) { // reset highlighting if no-one wants to change it + rendererComponent.setForeground(UIUtil.getTableForeground(selected)); + } + } + private class MyMouseAdapter extends MouseAdapter { private final TableLinkMouseListener myLinkListener; @@ -346,6 +372,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component rendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); setBackground(isSelected ? table.getSelectionBackground() : JBColor.WHITE); + applyHighlighters(rendererComponent, row, isSelected); return rendererComponent; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/AbstractPaddingCellRender.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/AbstractPaddingCellRender.java index e802a2ecbb6e..fac9b67225bc 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/AbstractPaddingCellRender.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/AbstractPaddingCellRender.java @@ -12,6 +12,7 @@ import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.graph.PaintInfo; import com.intellij.vcs.log.graph.render.GraphCommitCell; import com.intellij.vcs.log.ui.VcsLogColorManager; +import com.intellij.vcs.log.ui.frame.VcsLogGraphTable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,6 +28,7 @@ public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer private static final Logger LOG = Logger.getInstance(AbstractPaddingCellRender.class); @NotNull private final VcsLogDataHolder myDataHolder; + @NotNull private final VcsLogGraphTable myGraphTable; @NotNull private final RefPainter myRefPainter; @NotNull private final IssueLinkRenderer myIssueLinkRenderer; @@ -34,8 +36,10 @@ public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer @Nullable private PaintInfo myGraphImage; @Nullable private Collection myRefs; - protected AbstractPaddingCellRender(@NotNull VcsLogColorManager colorManager, @NotNull VcsLogDataHolder dataHolder) { + protected AbstractPaddingCellRender(@NotNull VcsLogColorManager colorManager, @NotNull VcsLogDataHolder dataHolder, + @NotNull VcsLogGraphTable table) { myDataHolder = dataHolder; + myGraphTable = table; myRefPainter = new RefPainter(colorManager, false); myIssueLinkRenderer = new IssueLinkRenderer(dataHolder.getProject(), this); } @@ -67,6 +71,7 @@ public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer append(""); appendFixedTextFragmentWidth(textPadding); + myGraphTable.applyHighlighters(this, row, isSelected); myIssueLinkRenderer.appendTextWithLinks(cell.getText()); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java index 4448cd499977..d2698e87a4fd 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java @@ -19,6 +19,7 @@ import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.graph.GraphFacade; import com.intellij.vcs.log.graph.PaintInfo; import com.intellij.vcs.log.ui.VcsLogColorManager; +import com.intellij.vcs.log.ui.frame.VcsLogGraphTable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,9 +27,9 @@ public class GraphCommitCellRender extends AbstractPaddingCellRender { @NotNull private GraphFacade myGraphFacade; - public GraphCommitCellRender(@NotNull VcsLogColorManager colorManager, - @NotNull VcsLogDataHolder dataHolder, @NotNull GraphFacade graphFacade) { - super(colorManager, dataHolder); + public GraphCommitCellRender(@NotNull VcsLogColorManager colorManager, @NotNull VcsLogDataHolder dataHolder, + @NotNull GraphFacade graphFacade, @NotNull VcsLogGraphTable table) { + super(colorManager, dataHolder, table); myGraphFacade = graphFacade; } From e10b40fba090c838ec115c15576af8df9b3ef098 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 9 Mar 2014 15:02:20 +0400 Subject: [PATCH 16/32] [log] Expose VcsLogUI & DataPack to the vcs-log-api * Introduce VcsLogUi interface to the API & to VcsLogDataKeys Provide an instance from the MainFrame. Provide information about current filters. * Introduce VcsLogDataPack, let DataPack implement this. Provide information about log providers map. --- .../com/intellij/vcs/log/VcsLogDataKeys.java | 1 + .../com/intellij/vcs/log/VcsLogDataPack.java | 28 +++++++++++++++++ .../src/com/intellij/vcs/log/VcsLogUi.java | 31 +++++++++++++++++++ .../com/intellij/vcs/log/data/DataPack.java | 25 ++++++++++----- .../intellij/vcs/log/data/VcsLogFilterer.java | 6 ++-- .../com/intellij/vcs/log/impl/VcsLogImpl.java | 6 ++-- .../intellij/vcs/log/impl/VcsLogManager.java | 10 +++--- .../log/ui/VcsLogQuickSettingsActions.java | 6 ++-- .../ui/{VcsLogUI.java => VcsLogUiImpl.java} | 30 ++++++++++++------ .../log/ui/filter/VcsLogClassicFilterUi.java | 6 ++-- .../vcs/log/ui/frame/BranchesPanel.java | 10 +++--- .../intellij/vcs/log/ui/frame/MainFrame.java | 11 ++++--- .../vcs/log/ui/frame/VcsLogGraphTable.java | 16 ++++++---- .../ui/tables/AbstractVcsLogTableModel.java | 10 +++--- .../vcs/log/ui/tables/EmptyTableModel.java | 4 +-- .../vcs/log/ui/tables/GraphTableModel.java | 6 ++-- .../SelectRevisionInGitLogAction.java | 4 +-- 17 files changed, 148 insertions(+), 62 deletions(-) create mode 100644 platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataPack.java create mode 100644 platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java rename platform/vcs-log/impl/src/com/intellij/vcs/log/ui/{VcsLogUI.java => VcsLogUiImpl.java} (93%) diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java index 3f0efa30084f..efff9fd271ef 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java @@ -23,5 +23,6 @@ import com.intellij.openapi.actionSystem.DataKey; public class VcsLogDataKeys { public static DataKey VSC_LOG = DataKey.create("Vcs.Log"); + public static DataKey VCS_LOG_UI = DataKey.create("Vcs.Log.Ui"); } diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataPack.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataPack.java new file mode 100644 index 000000000000..1cde2a525748 --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataPack.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.vcs.log; + +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public interface VcsLogDataPack { + + @NotNull + Map getLogProviders(); + +} diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java new file mode 100644 index 000000000000..c86ee12e087d --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java @@ -0,0 +1,31 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.vcs.log; + +import org.jetbrains.annotations.NotNull; + +public interface VcsLogUi { + + @NotNull + VcsLogFilterCollection getFilters(); + + @NotNull + VcsLogDataPack getDataPack(); + + void addHighlighter(@NotNull VcsLogHighlighter highlighter); + void removeHighlighter(@NotNull VcsLogHighlighter highlighter); + +} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java index 867431853d87..e13847df837e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java @@ -12,12 +12,13 @@ import org.jetbrains.annotations.NotNull; import java.util.*; import java.util.List; -public class DataPack { - private static final boolean USE_NEW_FACADE = true; +public class DataPack implements VcsLogDataPack { + private static final boolean USE_NEW_FACADE = true; @NotNull private final RefsModel myRefsModel; @NotNull private final GraphFacade myGraphFacade; + @NotNull private final Map myLogProviders; @NotNull public static DataPack build(@NotNull List commits, @@ -25,20 +26,21 @@ public class DataPack { @NotNull ProgressIndicator indicator, @NotNull NotNullFunction indexGetter, @NotNull NotNullFunction hashGetter, - @NotNull Map logProviders) { + @NotNull Map providers) { indicator.setText("Building graph..."); final RefsModel refsModel = new RefsModel(allRefs, indexGetter); - GraphColorManagerImpl colorManager = new GraphColorManagerImpl(refsModel, hashGetter, getRefManagerMap(logProviders)); + GraphColorManagerImpl colorManager = new GraphColorManagerImpl(refsModel, hashGetter, getRefManagerMap(providers)); if (USE_NEW_FACADE) { if (!commits.isEmpty()) { - return new DataPack(refsModel, GraphFacadeImpl.newInstance(commits, getBranchCommitHashIndexes(allRefs, indexGetter), colorManager)); + return new DataPack(refsModel, GraphFacadeImpl.newInstance(commits, getBranchCommitHashIndexes(allRefs, indexGetter), colorManager), + providers); } else { - return new DataPack(refsModel, new EmptyGraphFacade()); + return new DataPack(refsModel, new EmptyGraphFacade(), providers); } } else { GraphFacade graphFacade = new GraphFacadeBuilderImpl().build(commits, refsModel, colorManager); - return new DataPack(refsModel, graphFacade); + return new DataPack(refsModel, graphFacade, providers); } } @@ -62,9 +64,10 @@ public class DataPack { return map; } - private DataPack(@NotNull RefsModel refsModel, @NotNull GraphFacade graphFacade) { + private DataPack(@NotNull RefsModel refsModel, @NotNull GraphFacade graphFacade, @NotNull Map providers) { myRefsModel = refsModel; myGraphFacade = graphFacade; + myLogProviders = providers; } @NotNull @@ -77,4 +80,10 @@ public class DataPack { return myRefsModel; } + @NotNull + @Override + public Map getLogProviders() { + return myLogProviders; + } + } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java index a2989d16928f..5467caf1479b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java @@ -10,7 +10,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.impl.VcsLogUtil; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel; import com.intellij.vcs.log.ui.tables.EmptyTableModel; import com.intellij.vcs.log.ui.tables.GraphTableModel; @@ -28,9 +28,9 @@ public class VcsLogFilterer { private static final int LOAD_MORE_COMMITS_FIRST_STEP_LIMIT = 200; @NotNull private final VcsLogDataHolder myLogDataHolder; - @NotNull private final VcsLogUI myUI; + @NotNull private final VcsLogUiImpl myUI; - public VcsLogFilterer(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUI ui) { + public VcsLogFilterer(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUiImpl ui) { myLogDataHolder = logDataHolder; myUI = ui; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java index 244ca14b8ab6..6abda6ae2c54 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogImpl.java @@ -20,7 +20,7 @@ import com.intellij.ui.table.JBTable; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.VcsLogDataHolder; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,9 +35,9 @@ import java.util.List; public class VcsLogImpl implements VcsLog { @NotNull private final VcsLogDataHolder myDataHolder; - @NotNull private final VcsLogUI myUi; + @NotNull private final VcsLogUiImpl myUi; - public VcsLogImpl(@NotNull VcsLogDataHolder holder, @NotNull VcsLogUI ui) { + public VcsLogImpl(@NotNull VcsLogDataHolder holder, @NotNull VcsLogUiImpl ui) { myDataHolder = holder; myUi = ui; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java index 9d19ddd82217..7be55fbfe93b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java @@ -30,7 +30,7 @@ import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.data.VcsLogUiProperties; import com.intellij.vcs.log.ui.VcsLogColorManagerImpl; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -54,7 +54,7 @@ public class VcsLogManager implements Disposable { private PostponeableLogRefresher myLogRefresher; private volatile VcsLogDataHolder myLogDataHolder; - private volatile VcsLogUI myUi; + private volatile VcsLogUiImpl myUi; public VcsLogManager(@NotNull Project project, @NotNull ProjectLevelVcsManager vcsManager, @NotNull VcsLogSettings settings, @@ -75,7 +75,7 @@ public class VcsLogManager implements Disposable { myLogDataHolder.initialize(new PairConsumer() { @Override public void consume(VcsLogDataHolder vcsLogDataHolder, DataPack dataPack) { - VcsLogUI logUI = new VcsLogUI(vcsLogDataHolder, myProject, mySettings, + VcsLogUiImpl logUI = new VcsLogUiImpl(vcsLogDataHolder, myProject, mySettings, new VcsLogColorManagerImpl(logProviders.keySet()), myUiProperties, dataPack); myLogDataHolder = vcsLogDataHolder; myUi = logUI; @@ -124,10 +124,10 @@ public class VcsLogManager implements Disposable { } /** - * The instance of the {@link VcsLogUI} or null if the log was not initialized yet. + * The instance of the {@link com.intellij.vcs.log.ui.VcsLogUiImpl} or null if the log was not initialized yet. */ @Nullable - public VcsLogUI getLogUi() { + public VcsLogUiImpl getLogUi() { return myUi; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java index e047633ea0c4..66af044ebcf0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogQuickSettingsActions.java @@ -38,7 +38,7 @@ public class VcsLogQuickSettingsActions extends DumbAwareAction { } VcsLogSettings settings = ServiceManager.getService(project, VcsLogSettings.class); VcsLogManager logManager = ServiceManager.getService(project, VcsLogManager.class); - VcsLogUI logUi = logManager.getLogUi(); + VcsLogUiImpl logUi = logManager.getLogUi(); if (logUi == null) { return; } @@ -70,9 +70,9 @@ public class VcsLogQuickSettingsActions extends DumbAwareAction { private static class MySettingsActionGroup extends ActionGroup { private final VcsLogSettings mySettings; - private final VcsLogUI myUi; + private final VcsLogUiImpl myUi; - public MySettingsActionGroup(VcsLogSettings settings, VcsLogUI ui) { + public MySettingsActionGroup(VcsLogSettings settings, VcsLogUiImpl ui) { mySettings = settings; myUi = ui; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java similarity index 93% rename from platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java rename to platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 02595cf95c7a..81a653896a6f 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -1,10 +1,12 @@ package com.intellij.vcs.log.ui; +import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.util.PairFunction; @@ -25,16 +27,13 @@ import javax.swing.table.AbstractTableModel; import javax.swing.table.TableModel; import java.awt.*; -/** - * @author erokhins - */ -public class VcsLogUI { +public class VcsLogUiImpl implements VcsLogUi, Disposable { public static final String POPUP_ACTION_GROUP = "Vcs.Log.ContextMenu"; public static final String TOOLBAR_ACTION_GROUP = "Vcs.Log.Toolbar"; public static final String VCS_LOG_TABLE_PLACE = "Vcs.Log.ContextMenu"; - private static final Logger LOG = Logger.getInstance(VcsLogUI.class); + private static final Logger LOG = Logger.getInstance(VcsLogUiImpl.class); @NotNull private final VcsLogDataHolder myLogDataHolder; @NotNull private final MainFrame myMainFrame; @@ -45,12 +44,14 @@ public class VcsLogUI { @NotNull private DataPack myDataPack; - public VcsLogUI(@NotNull VcsLogDataHolder logDataHolder, @NotNull Project project, @NotNull VcsLogSettings settings, - @NotNull VcsLogColorManager manager, @NotNull VcsLogUiProperties uiProperties, @NotNull DataPack initialDataPack) { + public VcsLogUiImpl(@NotNull VcsLogDataHolder logDataHolder, @NotNull Project project, @NotNull VcsLogSettings settings, + @NotNull VcsLogColorManager manager, @NotNull VcsLogUiProperties uiProperties, @NotNull DataPack initialDataPack) { myLogDataHolder = logDataHolder; myProject = project; myColorManager = manager; myDataPack = initialDataPack; + Disposer.register(logDataHolder, this); + myFilterer = new VcsLogFilterer(logDataHolder, this); myLog = new VcsLogImpl(myLogDataHolder, this); myMainFrame = new MainFrame(myLogDataHolder, this, project, settings, uiProperties, myLog, initialDataPack); @@ -235,7 +236,7 @@ public class VcsLogUI { } private void commitNotFound(@NotNull String commitHash) { - if (collectFilters().isEmpty()) { + if (getFilters().isEmpty()) { showMessage(MessageType.WARNING, "Commit " + commitHash + " not found"); } else { @@ -276,7 +277,7 @@ public class VcsLogUI { runUnderModalProgress("Applying filters...", new Runnable() { public void run() { final TIntHashSet previouslySelected = getSelectedCommits(); - final AbstractVcsLogTableModel newModel = myFilterer.applyFiltersAndUpdateUi(dataPack, collectFilters()); + final AbstractVcsLogTableModel newModel = myFilterer.applyFiltersAndUpdateUi(dataPack, getFilters()); UIUtil.invokeLaterIfNeeded(new Runnable() { @Override public void run() { @@ -299,8 +300,9 @@ public class VcsLogUI { applyFiltersAndUpdateUi(myDataPack); } + @Override @NotNull - public VcsLogFilterCollection collectFilters() { + public VcsLogFilterCollection getFilters() { return myMainFrame.getFilterUi().getFilters(); } @@ -335,18 +337,26 @@ public class VcsLogUI { return myLog; } + @Override @NotNull public DataPack getDataPack() { ApplicationManager.getApplication().assertIsDispatchThread(); return myDataPack; } + @Override public void addHighlighter(@NotNull VcsLogHighlighter highlighter) { getTable().addHighlighter(highlighter); } + @Override public void removeHighlighter(@NotNull VcsLogHighlighter highlighter) { getTable().removeHighlighter(highlighter); } + @Override + public void dispose() { + getTable().removeAllHighlighters(); + } + } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java index 2c85927e1e08..41449aac101a 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java @@ -30,7 +30,7 @@ import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.data.VcsLogUiProperties; import com.intellij.vcs.log.impl.VcsLogFilterCollectionImpl; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -42,7 +42,7 @@ import java.awt.event.ActionListener; public class VcsLogClassicFilterUi implements VcsLogFilterUi { @NotNull private final SearchTextField myTextFilter; - @NotNull private final VcsLogUI myUi; + @NotNull private final VcsLogUiImpl myUi; @NotNull private final DefaultActionGroup myActionGroup; @NotNull private final BranchFilterPopupComponent myBranchFilterComponent; @@ -50,7 +50,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { @NotNull private final DateFilterPopupComponent myDateFilterComponent; @NotNull private final StructureFilterPopupComponent myStructureFilterComponent; - public VcsLogClassicFilterUi(@NotNull VcsLogUI ui, @NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUiProperties uiProperties, + public VcsLogClassicFilterUi(@NotNull VcsLogUiImpl ui, @NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUiProperties uiProperties, @NotNull DataPack initialDataPack) { myUi = ui; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java index 5afedf91b560..985423280f16 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/BranchesPanel.java @@ -22,7 +22,7 @@ import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.data.VcsLogRefreshListener; import com.intellij.vcs.log.impl.SingletonRefGroup; import com.intellij.vcs.log.impl.VcsLogUtil; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import com.intellij.vcs.log.ui.render.RefPainter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -46,14 +46,14 @@ import static com.intellij.vcs.log.graph.render.PrintParameters.HEIGHT_CELL; public class BranchesPanel extends JPanel { private final VcsLogDataHolder myDataHolder; - private final VcsLogUI myUI; + private final VcsLogUiImpl myUI; private List myRefGroups; private final RefPainter myRefPainter; private Map myRefPositions = ContainerUtil.newHashMap(); - public BranchesPanel(@NotNull VcsLogDataHolder dataHolder, @NotNull VcsLogUI UI, @NotNull RefsModel initialRefsModel) { + public BranchesPanel(@NotNull VcsLogDataHolder dataHolder, @NotNull VcsLogUiImpl UI, @NotNull RefsModel initialRefsModel) { myDataHolder = dataHolder; myUI = UI; myRefGroups = getRefsToDisplayOnPanel(initialRefsModel); @@ -162,14 +162,14 @@ public class BranchesPanel extends JPanel { private final JBPopup myPopup; private final JBList myList; - private final VcsLogUI myUi; + private final VcsLogUiImpl myUi; private final RefPainter myRefPainter; private final SingleRefComponent myRendererComponent; private final ListCellRenderer myCellRenderer; - RefPopupComponent(RefGroup group, VcsLogUI ui, RefPainter refPainter) { + RefPopupComponent(RefGroup group, VcsLogUiImpl ui, RefPainter refPainter) { super(new BorderLayout()); myUi = ui; myRefPainter = refPainter; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index eea8332d5425..35ef12fcf204 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -22,7 +22,7 @@ import com.intellij.vcs.log.VcsLogSettings; import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.data.VcsLogUiProperties; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import com.intellij.vcs.log.ui.filter.VcsLogClassicFilterUi; import com.intellij.vcs.log.ui.filter.VcsLogFilterUi; import com.intellij.vcs.log.ui.tables.GraphTableModel; @@ -40,7 +40,7 @@ import java.util.List; public class MainFrame extends JPanel implements TypeSafeDataProvider { @NotNull private final VcsLogDataHolder myLogDataHolder; - @NotNull private final VcsLogUI myUI; + @NotNull private final VcsLogUiImpl myUI; @NotNull private final Project myProject; @NotNull private final VcsLogUiProperties myUiProperties; @NotNull private final VcsLog myLog; @@ -53,7 +53,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { @NotNull private final Splitter myDetailsSplitter; private final JComponent myToolbar; - public MainFrame(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUI vcsLogUI, @NotNull Project project, + public MainFrame(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUiImpl vcsLogUI, @NotNull Project project, @NotNull VcsLogSettings settings, @NotNull VcsLogUiProperties uiProperties, @NotNull VcsLog log, @NotNull DataPack initialDataPack) { // collect info @@ -195,7 +195,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { DefaultActionGroup toolbarGroup = new DefaultActionGroup(hideBranchesAction, showBranchesAction, showFullPatchAction, refreshAction, showDetailsAction); - toolbarGroup.add(ActionManager.getInstance().getAction(VcsLogUI.TOOLBAR_ACTION_GROUP)); + toolbarGroup.add(ActionManager.getInstance().getAction(VcsLogUiImpl.TOOLBAR_ACTION_GROUP)); DefaultActionGroup mainGroup = new DefaultActionGroup(); mainGroup.add(myFilterUi.getFilterActionComponents()); @@ -224,6 +224,9 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { if (VcsLogDataKeys.VSC_LOG == key) { sink.put(key, myLog); } + else if (VcsLogDataKeys.VCS_LOG_UI == key) { + sink.put(key, myUI); + } else if (VcsDataKeys.CHANGES.equals(key)) { List selectedChanges = getSelectedChanges(); if (selectedChanges != null) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java index 4aab76c67bd9..5b1e1a0e7a0e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java @@ -22,7 +22,7 @@ import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.graph.*; import com.intellij.vcs.log.graph.render.GraphCommitCell; import com.intellij.vcs.log.graph.render.PositionUtil; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import com.intellij.vcs.log.ui.render.GraphCommitCellRender; import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel; import org.jetbrains.annotations.NotNull; @@ -50,7 +50,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C private static final int MAX_ROWS_TO_CALC_WIDTH = 1000; private static final int MAX_ROWS_TO_CALC_OFFSET = 100; - @NotNull private final VcsLogUI myUI; + @NotNull private final VcsLogUiImpl myUI; private final VcsLogDataHolder myLogDataHolder; private final GraphCommitCellRender myGraphCommitCellRender; @@ -61,7 +61,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C @NotNull private DataPack myDataPack; - public VcsLogGraphTable(@NotNull VcsLogUI UI, @NotNull final VcsLogDataHolder logDataHolder, @NotNull DataPack initialDataPack) { + public VcsLogGraphTable(@NotNull VcsLogUiImpl UI, @NotNull final VcsLogDataHolder logDataHolder, @NotNull DataPack initialDataPack) { super(); myUI = UI; myLogDataHolder = logDataHolder; @@ -90,7 +90,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C addMouseMotionListener(mouseAdapter); addMouseListener(mouseAdapter); - PopupHandler.installPopupHandler(this, VcsLogUI.POPUP_ACTION_GROUP, VcsLogUI.VCS_LOG_TABLE_PLACE); + PopupHandler.installPopupHandler(this, VcsLogUiImpl.POPUP_ACTION_GROUP, VcsLogUiImpl.VCS_LOG_TABLE_PLACE); } @Override @@ -252,6 +252,10 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C myHighlighters.remove(highlighter); } + public void removeAllHighlighters() { + myHighlighters.clear(); + } + public void applyHighlighters(@NotNull Component rendererComponent, int row, boolean selected) { boolean fgUpdated = false; for (VcsLogHighlighter highlighter : myHighlighters) { @@ -339,11 +343,11 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C private static class RootCellRenderer extends JPanel implements TableCellRenderer { - @NotNull private final VcsLogUI myUi; + @NotNull private final VcsLogUiImpl myUi; @NotNull private Color myColor = UIUtil.getTableBackground(); - RootCellRenderer(@NotNull VcsLogUI ui) { + RootCellRenderer(@NotNull VcsLogUiImpl ui) { myUi = ui; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java index ace90a0c6090..d18c645f4ed7 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/AbstractVcsLogTableModel.java @@ -12,7 +12,7 @@ import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.LoadMoreStage; import com.intellij.vcs.log.data.LoadingDetails; import com.intellij.vcs.log.data.VcsLogDataHolder; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,14 +34,14 @@ public abstract class AbstractVcsLogTableModel extends Abstra private static final String[] COLUMN_NAMES = {"", "Subject", "Author", "Date"}; @NotNull private final VcsLogDataHolder myLogDataHolder; - @NotNull protected final VcsLogUI myUi; + @NotNull protected final VcsLogUiImpl myUi; @NotNull protected final DataPack myDataPack; @NotNull private final LoadMoreStage myLoadMoreStage; @NotNull private final AtomicBoolean myLoadMoreWasRequested = new AtomicBoolean(); - protected AbstractVcsLogTableModel(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUI ui, @NotNull DataPack dataPack, + protected AbstractVcsLogTableModel(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUiImpl ui, @NotNull DataPack dataPack, @NotNull LoadMoreStage loadMoreStage) { myLogDataHolder = logDataHolder; myUi = ui; @@ -72,7 +72,7 @@ public abstract class AbstractVcsLogTableModel extends Abstra if (myLoadMoreWasRequested.compareAndSet(false, true) // Don't send the request to VCS twice && myLoadMoreStage != LoadMoreStage.ALL_REQUESTED) { // or when everything possible is loaded myUi.getTable().setPaintBusy(true); - myUi.getFilterer().requestVcs(myDataPack, myUi.collectFilters(), myLoadMoreStage, onLoaded); + myUi.getFilterer().requestVcs(myDataPack, myUi.getFilters(), myLoadMoreStage, onLoaded); } } @@ -112,7 +112,7 @@ public abstract class AbstractVcsLogTableModel extends Abstra * Returns true if not all data has been loaded, i.e. there is sense to {@link #requestToLoadMore(Runnable) request more data}. */ public boolean canRequestMore() { - return !myUi.collectFilters().isEmpty() && myLoadMoreStage != LoadMoreStage.ALL_REQUESTED; + return !myUi.getFilters().isEmpty() && myLoadMoreStage != LoadMoreStage.ALL_REQUESTED; } /** diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/EmptyTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/EmptyTableModel.java index 00ad86a27cbf..0f5ae1f8285f 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/EmptyTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/EmptyTableModel.java @@ -23,7 +23,7 @@ import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.LoadMoreStage; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.graph.render.GraphCommitCell; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,7 +32,7 @@ import java.util.Collections; public class EmptyTableModel extends AbstractVcsLogTableModel { public EmptyTableModel(@NotNull DataPack dataPack, @NotNull VcsLogDataHolder logDataHolder, - @NotNull VcsLogUI ui, @NotNull LoadMoreStage loadMoreStage) { + @NotNull VcsLogUiImpl ui, @NotNull LoadMoreStage loadMoreStage) { super(logDataHolder, ui, dataPack, loadMoreStage); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java index 4be4d59beb36..c7524ee5adc1 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java @@ -12,7 +12,7 @@ import com.intellij.vcs.log.data.LoadMoreStage; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.graph.render.GraphCommitCell; import com.intellij.vcs.log.impl.VcsLogUtil; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,7 +27,7 @@ public class GraphTableModel extends AbstractVcsLogTableModel { @NotNull private final DataPack myDataPack; @NotNull private final VcsLogDataHolder myDataHolder; - public GraphTableModel(@NotNull DataPack dataPack, @NotNull VcsLogDataHolder dataHolder, @NotNull VcsLogUI UI, + public GraphTableModel(@NotNull DataPack dataPack, @NotNull VcsLogDataHolder dataHolder, @NotNull VcsLogUiImpl UI, @NotNull LoadMoreStage loadMoreStage) { super(dataHolder, UI, dataPack, loadMoreStage); myDataPack = dataPack; @@ -44,7 +44,7 @@ public class GraphTableModel extends AbstractVcsLogTableModel { if (!myDataHolder.isFullLogShowing()) { myDataHolder.showFullLog(onLoaded); } - else if (!myUi.collectFilters().isEmpty()) { + else if (!myUi.getFilters().isEmpty()) { super.requestToLoadMore(onLoaded); } } diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/SelectRevisionInGitLogAction.java b/plugins/git4idea/src/git4idea/history/wholeTree/SelectRevisionInGitLogAction.java index 7c88a1cdeb24..dfd355813dbb 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/SelectRevisionInGitLogAction.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/SelectRevisionInGitLogAction.java @@ -16,7 +16,7 @@ import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; import com.intellij.vcs.log.impl.VcsLogContentProvider; import com.intellij.vcs.log.impl.VcsLogManager; -import com.intellij.vcs.log.ui.VcsLogUI; +import com.intellij.vcs.log.ui.VcsLogUiImpl; import git4idea.i18n.GitBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -56,7 +56,7 @@ public class SelectRevisionInGitLogAction extends DumbAwareAction { Runnable selectCommit = new Runnable() { @Override public void run() { - VcsLogUI logUi = log.getLogUi(); + VcsLogUiImpl logUi = log.getLogUi(); if (logUi == null) { return; } From 70668542620aa8c7e7bd3d5ff4147020bb968faa Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 9 Mar 2014 16:27:52 +0400 Subject: [PATCH 17/32] [log] Introduce VcsLogDataProvider to the API as part of VcsLogDataHolder * Provide getHash and getCommitIndex methods rename putHash -> getCommitIndex: this name looks more clear. --- .../com/intellij/vcs/log/VcsLogDataKeys.java | 1 + .../intellij/vcs/log/VcsLogDataProvider.java | 29 +++++++++++++++++++ .../vcs/log/data/VcsLogDataHolder.java | 14 +++++---- .../intellij/vcs/log/data/VcsLogFilterer.java | 2 +- .../log/impl/VcsLogObjectsFactoryImpl.java | 2 +- .../intellij/vcs/log/ui/frame/MainFrame.java | 3 ++ .../vcs/log/ui/tables/GraphTableModel.java | 2 +- 7 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataProvider.java diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java index efff9fd271ef..d2a8b459d920 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java @@ -24,5 +24,6 @@ public class VcsLogDataKeys { public static DataKey VSC_LOG = DataKey.create("Vcs.Log"); public static DataKey VCS_LOG_UI = DataKey.create("Vcs.Log.Ui"); + public static DataKey VCS_LOG_DATA_PROVIDER = DataKey.create("Vcs.Log.DataProvider"); } diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataProvider.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataProvider.java new file mode 100644 index 000000000000..78577be55d24 --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.vcs.log; + +import org.jetbrains.annotations.NotNull; + +/** + */ +public interface VcsLogDataProvider { + + @NotNull + Hash getHash(int commitIndex); + + int getCommitIndex(@NotNull Hash hash); + +} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java index 1373aa81e84f..c2822dcd3f48 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java @@ -82,7 +82,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * * @author Kirill Likhodedov */ -public class VcsLogDataHolder implements Disposable { +public class VcsLogDataHolder implements Disposable, VcsLogDataProvider { public static final Topic REFRESH_COMPLETED = Topic.create("Vcs.Log.Completed", VcsLogRefreshListener.class); @@ -177,12 +177,13 @@ public class VcsLogDataHolder implements Disposable { @NotNull @Override public Integer fun(Hash hash) { - return putHash(hash); + return getCommitIndex(hash); } }; myContainingBranchesGetter = new ContainingBranchesGetter(this, this); } + @Override @NotNull public Hash getHash(int commitIndex) { try { @@ -197,7 +198,8 @@ public class VcsLogDataHolder implements Disposable { } } - public int putHash(@NotNull Hash hash) { + @Override + public int getCommitIndex(@NotNull Hash hash) { try { return myHashMap.getOrPut(hash); } @@ -839,15 +841,15 @@ public class VcsLogDataHolder implements Disposable { } public CompactCommit(Hash hash, List parents, long time) { - myHashIndex = putHash(hash); + myHashIndex = getCommitIndex(hash); myTime = time; if (!parents.isEmpty()) { - myParent = putHash(parents.get(0)); + myParent = getCommitIndex(parents.get(0)); if (parents.size() > 1) { myOtherParents = new int[parents.size() - 1]; for (int i = 0; i < parents.size() - 1; i++) { - myOtherParents[i]= putHash(parents.get(i + 1)); + myOtherParents[i]= getCommitIndex(parents.get(i + 1)); } } else { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java index 5467caf1479b..e07e92fda5ac 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java @@ -64,7 +64,7 @@ public class VcsLogFilterer { final Set commitSet = ContainerUtil.map2Set(filteredCommits, new Function() { @Override public Integer fun(Hash hash) { - return myLogDataHolder.putHash(hash); + return myLogDataHolder.getCommitIndex(hash); } }); return new Condition() { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java index 7ad114a066c3..79ce3a9565e7 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java @@ -85,7 +85,7 @@ public class VcsLogObjectsFactoryImpl implements VcsLogObjectsFactory { LOG.error("The log data holder should have been initialized at this point"); return -1; } - return dataHolder.putHash(hash); + return dataHolder.getCommitIndex(hash); } }, commitHash, name, type, root); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index 35ef12fcf204..655c99ef575d 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -227,6 +227,9 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { else if (VcsLogDataKeys.VCS_LOG_UI == key) { sink.put(key, myUI); } + else if (VcsLogDataKeys.VCS_LOG_DATA_PROVIDER == key) { + sink.put(key, myLogDataHolder); + } else if (VcsDataKeys.CHANGES.equals(key)) { List selectedChanges = getSelectedChanges(); if (selectedChanges != null) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java index c7524ee5adc1..2c58b47cf222 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/tables/GraphTableModel.java @@ -92,7 +92,7 @@ public class GraphTableModel extends AbstractVcsLogTableModel { @Override public int getRowOfCommit(@NotNull final Hash hash) { - final int commitIndex = myDataHolder.putHash(hash); + final int commitIndex = myDataHolder.getCommitIndex(hash); return ContainerUtil.indexOf(VcsLogUtil.getVisibleCommits(myDataPack.getGraphFacade()), new Condition() { @Override public boolean value(Integer integer) { From 542550f65dfcdece5bfb81f3371a738f2a281953 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 9 Mar 2014 16:37:52 +0400 Subject: [PATCH 18/32] [log] make constants final --- .../api/src/com/intellij/vcs/log/VcsLogDataKeys.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java index d2a8b459d920..a7aace2d2332 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataKeys.java @@ -22,8 +22,8 @@ import com.intellij.openapi.actionSystem.DataKey; */ public class VcsLogDataKeys { - public static DataKey VSC_LOG = DataKey.create("Vcs.Log"); - public static DataKey VCS_LOG_UI = DataKey.create("Vcs.Log.Ui"); - public static DataKey VCS_LOG_DATA_PROVIDER = DataKey.create("Vcs.Log.DataProvider"); + public static final DataKey VSC_LOG = DataKey.create("Vcs.Log"); + public static final DataKey VCS_LOG_UI = DataKey.create("Vcs.Log.Ui"); + public static final DataKey VCS_LOG_DATA_PROVIDER = DataKey.create("Vcs.Log.DataProvider"); } From a54504c40867ca962fb1a101ded89b6eff9e4918 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 9 Mar 2014 16:41:19 +0400 Subject: [PATCH 19/32] [log] repaint ui after adding highlighter --- .../vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 81a653896a6f..0197ec363a65 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -347,11 +347,13 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { @Override public void addHighlighter(@NotNull VcsLogHighlighter highlighter) { getTable().addHighlighter(highlighter); + repaintUI(); } @Override public void removeHighlighter(@NotNull VcsLogHighlighter highlighter) { getTable().removeHighlighter(highlighter); + repaintUI(); } @Override From 3d8130382bfd427118e23fce7422ddbed5fe5530 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 10 Mar 2014 15:03:26 +0400 Subject: [PATCH 20/32] [log] Expose the VcsLogFilterUi to the API, let set filter value + Since VcsLogFilterUi gets into API, remove getFilters from VcsLogUi, substituting it with getFilterUi(). --- .../intellij/vcs/log/VcsLogBranchFilter.java | 1 + .../com/intellij/vcs/log/VcsLogFilterUi.java | 22 +++++++++++++ .../src/com/intellij/vcs/log/VcsLogUi.java | 2 +- .../com/intellij/vcs/log/ui/VcsLogUiImpl.java | 7 +++- .../MultipleValueFilterPopupComponent.java | 6 ++-- .../log/ui/filter/VcsLogClassicFilterUi.java | 20 ++++++++--- .../vcs/log/ui/filter/VcsLogFilterUi.java | 33 ------------------- .../intellij/vcs/log/ui/frame/MainFrame.java | 4 +-- 8 files changed, 50 insertions(+), 45 deletions(-) create mode 100644 platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterUi.java delete mode 100644 platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFilterUi.java diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java index dfa78da2fab3..60e588ded1cc 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java @@ -27,6 +27,7 @@ public interface VcsLogBranchFilter extends VcsLogFilter { @NotNull Collection getBranchNames(); + // TODO remove from the API @NotNull Collection getMatchingHeads(); diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterUi.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterUi.java new file mode 100644 index 000000000000..a4cf4b903d2e --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterUi.java @@ -0,0 +1,22 @@ +package com.intellij.vcs.log; + +import org.jetbrains.annotations.NotNull; + +/** + * Graphical UI for filtering commits in the log. + */ +public interface VcsLogFilterUi { + + /** + * Returns the filters currently active, i.e. switched on by user. + */ + @NotNull + VcsLogFilterCollection getFilters(); + + /** + * Sets the given filter to the given value and updates the log view.
+ * Note: only VcsLogBranchFilter is currently supported. + */ + void setFilter(@NotNull VcsLogFilter filter); + +} diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java index c86ee12e087d..18a355816e1f 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; public interface VcsLogUi { @NotNull - VcsLogFilterCollection getFilters(); + VcsLogFilterUi getFilterUi(); @NotNull VcsLogDataPack getDataPack(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 0197ec363a65..60fe23d15a86 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -300,7 +300,6 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { applyFiltersAndUpdateUi(myDataPack); } - @Override @NotNull public VcsLogFilterCollection getFilters() { return myMainFrame.getFilterUi().getFilters(); @@ -337,6 +336,12 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { return myLog; } + @NotNull + @Override + public VcsLogFilterUi getFilterUi() { + return myMainFrame.getFilterUi(); + } + @Override @NotNull public DataPack getDataPack() { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultipleValueFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultipleValueFilterPopupComponent.java index 47872d4ed5dc..3a48f8e1d0e1 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultipleValueFilterPopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/MultipleValueFilterPopupComponent.java @@ -69,7 +69,7 @@ abstract class MultipleValueFilterPopupComponent ex return group; } - private void apply(@Nullable Collection values, String text, String tooltip) { + void apply(@Nullable Collection values, @NotNull String text, @NotNull String tooltip) { mySelectedValues = values; applyFilters(); setValue(text, tooltip); @@ -79,7 +79,7 @@ abstract class MultipleValueFilterPopupComponent ex } @NotNull - private static String displayableText(@NotNull Collection values) { + static String displayableText(@NotNull Collection values) { if (values.size() == 1) { return values.iterator().next(); } @@ -87,7 +87,7 @@ abstract class MultipleValueFilterPopupComponent ex } @NotNull - private static String tooltip(@NotNull Collection values) { + static String tooltip(@NotNull Collection values) { return StringUtil.join(values, ", "); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java index 41449aac101a..88e27fab1aa4 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java @@ -24,8 +24,7 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.ui.SearchTextField; import com.intellij.ui.SearchTextFieldWithStoredHistory; import com.intellij.util.ui.UIUtil; -import com.intellij.vcs.log.VcsLogFilterCollection; -import com.intellij.vcs.log.VcsLogTextFilter; +import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.data.VcsLogUiProperties; @@ -36,6 +35,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.Collection; /** */ @@ -76,12 +76,14 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { myActionGroup.add(new FilterActionComponent(myStructureFilterComponent)); } - @Override public void updateDataPack(@NotNull DataPack dataPack) { myBranchFilterComponent.updateRefsModel(dataPack.getRefsModel()); } - @Override + /** + * Returns filter components which will be added to the Log toolbar. + */ + @NotNull public ActionGroup getFilterActionComponents() { return myActionGroup; } @@ -94,11 +96,19 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { myDateFilterComponent.getFilter(), textFilter, myStructureFilterComponent.getFilter()); } + @Override + public void setFilter(@NotNull VcsLogFilter filter) { + if (filter instanceof VcsLogBranchFilter) { + Collection values = ((VcsLogBranchFilter)filter).getBranchNames(); + myBranchFilterComponent.apply(values, MultipleValueFilterPopupComponent.displayableText(values), + MultipleValueFilterPopupComponent.tooltip(values)); + } + } + void applyFilters() { myUi.applyFiltersAndUpdateUi(); } - private static class TextFilterComponent extends DumbAwareAction implements CustomComponentAction { private final SearchTextField mySearchField; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFilterUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFilterUi.java deleted file mode 100644 index a9e2e648343c..000000000000 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFilterUi.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.intellij.vcs.log.ui.filter; - -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.vcs.log.VcsLogFilterCollection; -import com.intellij.vcs.log.data.DataPack; -import org.jetbrains.annotations.NotNull; - -/** - * Graphical UI for filtering commits in the log. - * - * @author Kirill Likhodedov - */ -public interface VcsLogFilterUi { - - /** - * Returns filter components which will be added to the Log toolbar. - */ - ActionGroup getFilterActionComponents(); - - /** - * Returns the filters currently active, i.e. switched on by user. - */ - @NotNull - VcsLogFilterCollection getFilters(); - - /** - * Informs components that the actual DataPack has been updated (e.g. due to a log refresh).
- * Components may want to update their fields and/or rebuild. - * @param dataPack new data pack. - */ - void updateDataPack(@NotNull DataPack dataPack); - -} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java index 655c99ef575d..4282f39884fc 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/MainFrame.java @@ -24,7 +24,7 @@ import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.data.VcsLogUiProperties; import com.intellij.vcs.log.ui.VcsLogUiImpl; import com.intellij.vcs.log.ui.filter.VcsLogClassicFilterUi; -import com.intellij.vcs.log.ui.filter.VcsLogFilterUi; +import com.intellij.vcs.log.VcsLogFilterUi; import com.intellij.vcs.log.ui.tables.GraphTableModel; import icons.VcsLogIcons; import org.jetbrains.annotations.NotNull; @@ -44,7 +44,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider { @NotNull private final Project myProject; @NotNull private final VcsLogUiProperties myUiProperties; @NotNull private final VcsLog myLog; - @NotNull private final VcsLogFilterUi myFilterUi; + @NotNull private final VcsLogClassicFilterUi myFilterUi; @NotNull private final JBLoadingPanel myChangesLoadingPane; @NotNull private final VcsLogGraphTable myGraphTable; From d282a0ed733053f4f38999a0dab1a279f76ce010 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 10 Mar 2014 15:11:31 +0400 Subject: [PATCH 21/32] [log] Expose VcsLogRefs into API * For now just return branches, since it is all what's needed. * Keep getRefsModel() until it is decided what methods should be exposed --- .../com/intellij/vcs/log/VcsLogDataPack.java | 3 ++ .../src/com/intellij/vcs/log/VcsLogRefs.java | 33 +++++++++++++++++++ .../com/intellij/vcs/log/data/DataPack.java | 6 ++++ .../com/intellij/vcs/log/data/RefsModel.java | 7 ++-- 4 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogRefs.java diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataPack.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataPack.java index 1cde2a525748..fd0afe998a3e 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataPack.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDataPack.java @@ -25,4 +25,7 @@ public interface VcsLogDataPack { @NotNull Map getLogProviders(); + @NotNull + VcsLogRefs getRefs(); + } diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogRefs.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogRefs.java new file mode 100644 index 000000000000..53338124f735 --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogRefs.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.vcs.log; + +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +/** + * Collection of {@link VcsRef branches & tags references} which are in the log. + */ +public interface VcsLogRefs { + + /** + * Returns all branches. + */ + @NotNull + Collection getBranches(); + +} diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java index e13847df837e..9b13d1db0ed4 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java @@ -75,6 +75,12 @@ public class DataPack implements VcsLogDataPack { return myGraphFacade; } + @NotNull + @Override + public VcsLogRefs getRefs() { + return myRefsModel; + } + @NotNull public RefsModel getRefsModel() { return myRefsModel; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/RefsModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/RefsModel.java index 98d4fe2c09bb..630ae43f5465 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/RefsModel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/RefsModel.java @@ -6,6 +6,7 @@ import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.vcs.log.Hash; +import com.intellij.vcs.log.VcsLogRefs; import com.intellij.vcs.log.VcsRef; import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.NotNull; @@ -14,10 +15,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -/** - * @author erokhins - */ -public class RefsModel { +public class RefsModel implements VcsLogRefs { @NotNull private final Collection myBranches; @NotNull private final MultiMap myRefsToHashes; @@ -80,6 +78,7 @@ public class RefsModel { return myRefsToIndices.containsKey(index) ? myRefsToIndices.get(index) : Collections.emptyList(); } + @Override @NotNull public Collection getBranches() { return myBranches; From eff05eab252e0cfaac1f7f32f8c78bd598db446d Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 10 Mar 2014 16:44:31 +0400 Subject: [PATCH 22/32] [log] Add ability to reuse branches filter popup --- .../ui/filter/BranchFilterPopupComponent.java | 63 +++++++++++-------- .../log/ui/filter/VcsLogClassicFilterUi.java | 4 +- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java index 7d650c5af9e0..0af25568ed60 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java @@ -16,14 +16,14 @@ package com.intellij.vcs.log.ui.filter; import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; -import com.intellij.vcs.log.data.RefsModel; +import com.intellij.vcs.log.data.DataPack; import com.intellij.vcs.log.data.VcsLogBranchFilterImpl; -import com.intellij.vcs.log.data.VcsLogDataHolder; import com.intellij.vcs.log.data.VcsLogUiProperties; import com.intellij.vcs.log.impl.VcsLogUtil; import org.jetbrains.annotations.NotNull; @@ -31,25 +31,21 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent { +public class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent { - @NotNull private final VcsLogDataHolder myDataHolder; @NotNull private final VcsLogUiProperties myUiProperties; - @NotNull private RefsModel myRefsModel; + @NotNull private VcsLogDataPack myDataPack; - BranchFilterPopupComponent(@NotNull VcsLogClassicFilterUi filterUi, - @NotNull VcsLogDataHolder dataHolder, - @NotNull RefsModel refsModel, - @NotNull VcsLogUiProperties uiProperties) { + public BranchFilterPopupComponent(@NotNull VcsLogClassicFilterUi filterUi, @NotNull VcsLogDataPack dataPack, + @NotNull VcsLogUiProperties uiProperties) { super(filterUi, "Branch"); - myDataHolder = dataHolder; - myRefsModel = refsModel; + myDataPack = dataPack; myUiProperties = uiProperties; } - void updateRefsModel(@NotNull RefsModel refsModel) { - myRefsModel = refsModel; + void updateDataPack(@NotNull DataPack dataPack) { + myDataPack = dataPack; } @Override @@ -59,39 +55,56 @@ class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent() { + @Override + public AnAction fun(String name) { + return createPredefinedValueAction(Collections.singleton(name)); + } + })); + return actionGroup; + } + + public static ActionGroup constructActionGroup(@NotNull VcsLogDataPack dataPack, @Nullable ActionGroup recentItemsGroup, + @NotNull Function actionGetter) { + Groups groups = prepareGroups(dataPack); + return getFilteredActionGroup(groups, recentItemsGroup, actionGetter); + } + + private static Groups prepareGroups(@NotNull VcsLogDataPack dataPack) { Groups filteredGroups = new Groups(); - Collection allRefs = myRefsModel.getBranches(); + Collection allRefs = dataPack.getRefs().getBranches(); for (Map.Entry> entry : VcsLogUtil.groupRefsByRoot(allRefs).entrySet()) { VirtualFile root = entry.getKey(); Collection refs = entry.getValue(); - VcsLogProvider provider = myDataHolder.getLogProvider(root); + VcsLogProvider provider = dataPack.getLogProviders().get(root); VcsLogRefManager refManager = provider.getReferenceManager(); List refGroups = refManager.group(refs); orderRefGroups(refGroups, filteredGroups); } - - actionGroup.add(getFilteredActionGroup(filteredGroups)); - return actionGroup; + return filteredGroups; } - private DefaultActionGroup getFilteredActionGroup(Groups groups) { + private static DefaultActionGroup getFilteredActionGroup(@NotNull Groups groups, @Nullable ActionGroup recentItems, + @NotNull Function actionGetter) { DefaultActionGroup actionGroup = new DefaultActionGroup(); for (String single : groups.singletonGroups) { - actionGroup.add(createPredefinedValueAction(Collections.singleton(single))); + actionGroup.add(actionGetter.fun(single)); + } + if (recentItems != null) { + actionGroup.add(recentItems); } - actionGroup.add(createRecentItemsActionGroup()); for (Map.Entry> group : groups.expandedGroups.entrySet()) { actionGroup.addSeparator(group.getKey()); for (String action : group.getValue()) { - actionGroup.add(createPredefinedValueAction(Collections.singleton(action))); + actionGroup.add(actionGetter.fun(action)); } } actionGroup.addSeparator(); for (Map.Entry> group : groups.collapsedGroups.entrySet()) { DefaultActionGroup popupGroup = new DefaultActionGroup(group.getKey(), true); for (String action : group.getValue()) { - popupGroup.add(createPredefinedValueAction(Collections.singleton(action))); + popupGroup.add(actionGetter.fun(action)); } actionGroup.add(popupGroup); } @@ -145,7 +158,7 @@ class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent allBranches = myRefsModel.getBranches(); + Collection allBranches = myDataPack.getRefs().getBranches(); return new VcsLogBranchFilterImpl(allBranches, getSelectedValues()); } @@ -165,7 +178,7 @@ class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent getAllValues() { - return ContainerUtil.map(myRefsModel.getBranches(), new Function() { + return ContainerUtil.map(myDataPack.getRefs().getBranches(), new Function() { @Override public String fun(VcsRef ref) { return ref.getName(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java index 88e27fab1aa4..d33e2ef67ec1 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java @@ -63,7 +63,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { } }); - myBranchFilterComponent = new BranchFilterPopupComponent(this, logDataHolder, initialDataPack.getRefsModel(), uiProperties); + myBranchFilterComponent = new BranchFilterPopupComponent(this, initialDataPack, uiProperties); myUserFilterComponent = new UserFilterPopupComponent(this, logDataHolder, uiProperties); myDateFilterComponent = new DateFilterPopupComponent(this); myStructureFilterComponent = new StructureFilterPopupComponent(this, logDataHolder.getRoots()); @@ -77,7 +77,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi { } public void updateDataPack(@NotNull DataPack dataPack) { - myBranchFilterComponent.updateRefsModel(dataPack.getRefsModel()); + myBranchFilterComponent.updateDataPack(dataPack); } /** From 881645aad510fc767e5e2aad900af2720852f948 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 10 Mar 2014 16:46:18 +0400 Subject: [PATCH 23/32] [log] Add ability to listen to possible filter changes --- .../vcs/log/VcsLogFilterChangeListener.java | 22 +++++++++++++++++++ .../src/com/intellij/vcs/log/VcsLogUi.java | 3 +++ .../com/intellij/vcs/log/ui/VcsLogUiImpl.java | 21 ++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterChangeListener.java diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterChangeListener.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterChangeListener.java new file mode 100644 index 000000000000..81f20021f573 --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterChangeListener.java @@ -0,0 +1,22 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.vcs.log; + +public interface VcsLogFilterChangeListener { + + void filtersPossiblyChanged(); + +} diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java index 18a355816e1f..456a6d76bec7 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUi.java @@ -28,4 +28,7 @@ public interface VcsLogUi { void addHighlighter(@NotNull VcsLogHighlighter highlighter); void removeHighlighter(@NotNull VcsLogHighlighter highlighter); + void addFilterChangeListener(@NotNull VcsLogFilterChangeListener listener); + void removeFilterChangeListener(@NotNull VcsLogFilterChangeListener listener); + } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 60fe23d15a86..4018c34b884b 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -10,6 +10,7 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.EmptyRunnable; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.util.PairFunction; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.*; @@ -26,6 +27,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableModel; import java.awt.*; +import java.util.Collection; public class VcsLogUiImpl implements VcsLogUi, Disposable { @@ -42,6 +44,8 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { @NotNull private final VcsLogFilterer myFilterer; @NotNull private final VcsLog myLog; + @NotNull private final Collection myFilterChangeListeners = ContainerUtil.newArrayList(); + @NotNull private DataPack myDataPack; public VcsLogUiImpl(@NotNull VcsLogDataHolder logDataHolder, @NotNull Project project, @NotNull VcsLogSettings settings, @@ -284,6 +288,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { myDataPack = dataPack; setModel(newModel, myDataPack, previouslySelected); myMainFrame.updateDataPack(myDataPack); + fireFilterChangeEvent(); repaintUI(); if (newModel.getRowCount() == 0) { // getValueAt won't be called for empty model => need to explicitly request to load more @@ -361,6 +366,22 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { repaintUI(); } + @Override + public void addFilterChangeListener(@NotNull VcsLogFilterChangeListener listener) { + myFilterChangeListeners.add(listener); + } + + @Override + public void removeFilterChangeListener(@NotNull VcsLogFilterChangeListener listener) { + myFilterChangeListeners.remove(listener); + } + + private void fireFilterChangeEvent() { + for (VcsLogFilterChangeListener listener : myFilterChangeListeners) { + listener.filtersPossiblyChanged(); + } + } + @Override public void dispose() { getTable().removeAllHighlighters(); From 7ac6e11cf70d97a425bc249cddcc06197cd9e9c5 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Mon, 10 Mar 2014 20:02:20 +0400 Subject: [PATCH 24/32] [log] IDEA-118947 Implement special highlighting for cherry-pick * Add DeepCompareAction as a toggle action to the vcs log toolbar. * Clicking on the button starts 'git cherry' in background to get commits non picked to the current branch. * Once completed, the log is highlighted so that picked commits appear in grey. * If initially there is no branch filter or several branches selected, propose user to select a single branch, apply filters and start collecting git cherry. * If branch filter changes, reset the highlighting. * If the log refreshes, restart all procedure to make sure that highlighting is correct, say, after cherry-picking on of the "black" commits. * But if current branch changes, reset the highlighting and don't restart the procedure. * DeepComparatorHolder maintains a single DeepComparator instance per each VcsLogUi (i.e. each vcs log). --- plugins/git4idea/src/META-INF/plugin.xml | 4 + .../src/git4idea/branch/DeepComparator.java | 264 ++++++++++++++++++ .../git4idea/branch/DeepComparatorHolder.java | 59 ++++ .../git4idea/branch/DeepCompareAction.java | 109 ++++++++ .../src/git4idea/commands/GitCommand.java | 1 + 5 files changed, 437 insertions(+) create mode 100644 plugins/git4idea/src/git4idea/branch/DeepComparator.java create mode 100644 plugins/git4idea/src/git4idea/branch/DeepComparatorHolder.java create mode 100644 plugins/git4idea/src/git4idea/branch/DeepCompareAction.java diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml index 3e36a5824540..de5eb2c8faa9 100644 --- a/plugins/git4idea/src/META-INF/plugin.xml +++ b/plugins/git4idea/src/META-INF/plugin.xml @@ -107,6 +107,9 @@ + @@ -174,6 +177,7 @@ serviceImplementation="git4idea.branch.GitBrancherImpl"/> + diff --git a/plugins/git4idea/src/git4idea/branch/DeepComparator.java b/plugins/git4idea/src/git4idea/branch/DeepComparator.java new file mode 100644 index 000000000000..1b46c6735f84 --- /dev/null +++ b/plugins/git4idea/src/git4idea/branch/DeepComparator.java @@ -0,0 +1,264 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea.branch; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.VcsNotifier; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.JBColor; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcs.log.*; +import com.intellij.vcs.log.data.DataPack; +import com.intellij.vcs.log.data.VcsLogDataHolder; +import com.intellij.vcs.log.data.VcsLogRefreshListener; +import com.intellij.vcs.log.impl.HashImpl; +import git4idea.GitBranch; +import git4idea.commands.GitCommand; +import git4idea.commands.GitLineHandler; +import git4idea.commands.GitLineHandlerAdapter; +import git4idea.repo.GitRepository; +import git4idea.repo.GitRepositoryManager; +import gnu.trove.TIntHashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; +import java.util.Map; + +public class DeepComparator implements Disposable { + + private static final Logger LOG = Logger.getInstance(DeepComparator.class); + + @NotNull private final Project myProject; + @NotNull private final GitRepositoryManager myRepositoryManager; + @NotNull private final VcsLogUi myUi; + @NotNull private final VcsLogFilterChangeListener myFilterChangeListener; + + @Nullable private VcsLogHighlighter myHighlighter; + @Nullable private MyTask myTask; + + @NotNull + public static DeepComparator getInstance(@NotNull Project project, @NotNull VcsLogUi ui) { + DeepComparatorHolder holder = ServiceManager.getService(project, DeepComparatorHolder.class); + return holder.getInstance(ui); + } + + DeepComparator(@NotNull Project project, @NotNull GitRepositoryManager manager, @NotNull VcsLogUi ui, @NotNull Disposable parent) { + myProject = project; + myRepositoryManager = manager; + myUi = ui; + Disposer.register(parent, this); + + myFilterChangeListener = new VcsLogFilterChangeListener() { + @Override + public void filtersPossiblyChanged() { + if (myTask == null) { // no task in progress => not interested in filter changes + return; + } + + VcsLogBranchFilter branchFilter = myUi.getFilterUi().getFilters().getBranchFilter(); + if (branchFilter == null || + branchFilter.getBranchNames().size() != 1 || + !branchFilter.getBranchNames().iterator().next().equals(myTask.myComparedBranch)) { + stopAndUnhighlight(); + } + } + }; + myUi.addFilterChangeListener(myFilterChangeListener); + + project.getMessageBus().connect(project).subscribe(VcsLogDataHolder.REFRESH_COMPLETED, new VcsLogRefreshListener() { + @Override + public void refresh(@NotNull DataPack dataPack) { + if (myTask == null) { // no task in progress => not interested in refresh events + return; + } + + // collect data + String comparedBranch = myTask.myComparedBranch; + Map repositoriesWithCurrentBranches = myTask.myRepositoriesWithCurrentBranches; + VcsLogDataProvider provider = myTask.myProvider; + + stopAndUnhighlight(); + + // highlight again + Map repositories = getRepositories(myUi.getDataPack().getLogProviders(), comparedBranch); + if (repositories.equals(repositoriesWithCurrentBranches)) { // but not if current branch changed + highlightInBackground(comparedBranch, provider); + } + } + }); + } + + public void highlightInBackground(@NotNull String branchToCompare, @NotNull VcsLogDataProvider dataProvider) { + if (myTask != null) { + LOG.error("Shouldn't be possible"); + return; + } + + Map repositories = getRepositories(myUi.getDataPack().getLogProviders(), branchToCompare); + if (repositories.isEmpty()) { + return; + } + + myTask = new MyTask(myProject, myUi, repositories, dataProvider, branchToCompare); + myTask.queue(); + } + + @NotNull + private Map getRepositories(@NotNull Map providers, + @NotNull String branchToCompare) { + Map repos = ContainerUtil.newHashMap(); + for (VirtualFile root : providers.keySet()) { + GitRepository repository = myRepositoryManager.getRepositoryForRoot(root); + if (repository == null || repository.getCurrentBranch() == null || + repository.getBranches().findBranchByName(branchToCompare) == null) { + continue; + } + repos.put(repository, repository.getCurrentBranch()); + } + return repos; + } + + public void stopAndUnhighlight() { + if (myTask != null) { + myTask.cancel(); + myTask = null; + } + if (myHighlighter != null) { + myUi.removeHighlighter(myHighlighter); + } + } + + @Override + public void dispose() { + stopAndUnhighlight(); + myUi.removeFilterChangeListener(myFilterChangeListener); + } + + public boolean hasHighlightingOrInProgress() { + return myTask != null; + } + + private class MyTask extends Task.Backgroundable { + + @NotNull private final Project myProject; + @NotNull private final VcsLogUi myUi; + @NotNull private final Map myRepositoriesWithCurrentBranches; + @NotNull private final VcsLogDataProvider myProvider; + @NotNull private final String myComparedBranch; + + @NotNull private final TIntHashSet myNonPickedCommits = new TIntHashSet(); + @Nullable private VcsException myException; + private boolean myCancelled; + + public MyTask(@NotNull Project project, @NotNull VcsLogUi ui, @NotNull Map repositoriesWithCurrentBranches, + @NotNull VcsLogDataProvider dataProvider, @NotNull String branchToCompare) { + super(project, "Comparing branches..."); + myProject = project; + myUi = ui; + myRepositoriesWithCurrentBranches = repositoriesWithCurrentBranches; + myProvider = dataProvider; + myComparedBranch = branchToCompare; + } + + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + for (Map.Entry entry : myRepositoriesWithCurrentBranches.entrySet()) { + GitRepository repo = entry.getKey(); + GitBranch currentBranch = entry.getValue(); + myNonPickedCommits.addAll(getNonPickedCommitsFromGit(myProject, repo.getRoot(), myProvider, + currentBranch.getName(), myComparedBranch).toArray()); + } + } + catch (VcsException e) { + LOG.warn(e); + myException = e; + } + } + + @Override + public void onSuccess() { + if (myCancelled) { + return; + } + + if (myException != null) { + VcsNotifier.getInstance(myProject).notifyError("Couldn't compare with branch " + myComparedBranch, myException.getMessage()); + return; + } + + if (myHighlighter != null) { + myUi.removeHighlighter(myHighlighter); + } + myHighlighter = new VcsLogHighlighter() { + @Nullable + @Override + public Color getForeground(int commitIndex, boolean isSelected) { + return !myNonPickedCommits.contains(commitIndex) ? JBColor.GRAY : null; + } + }; + myUi.addHighlighter(myHighlighter); + } + + public void cancel() { + myCancelled = true; + } + + @NotNull + private TIntHashSet getNonPickedCommitsFromGit(@NotNull Project project, @NotNull VirtualFile root, + @NotNull final VcsLogDataProvider dataProvider, + @NotNull String currentBranch, @NotNull String comparedBranch) throws VcsException { + GitLineHandler handler = new GitLineHandler(project, root, GitCommand.CHERRY); + handler.addParameters(currentBranch, comparedBranch); // upstream - current branch; head - compared branch + + final TIntHashSet pickedCommits = new TIntHashSet(); + handler.addLineListener(new GitLineHandlerAdapter() { + @Override + public void onLineAvailable(String line, Key outputType) { + // + 645caac042ff7fb1a5e3f7d348f00e9ceea5c317 + // - c3b9b90f6c26affd7e597ebf65db96de8f7e5860 + if (line.startsWith("+")) { + try { + line = line.substring(2).trim(); + int firstSpace = line.indexOf(' '); + if (firstSpace > 0) { + line = line.substring(0, firstSpace); // safety-check: take just the first word for sure + } + Hash hash = HashImpl.build(line); + pickedCommits.add(dataProvider.getCommitIndex(hash)); + } + catch (Exception e) { + LOG.error("Couldn't parse line [" + line + "]"); + } + } + } + }); + handler.runInCurrentThread(null); + return pickedCommits; + } + + } + +} diff --git a/plugins/git4idea/src/git4idea/branch/DeepComparatorHolder.java b/plugins/git4idea/src/git4idea/branch/DeepComparatorHolder.java new file mode 100644 index 000000000000..fdab43700b50 --- /dev/null +++ b/plugins/git4idea/src/git4idea/branch/DeepComparatorHolder.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea.branch; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcs.log.VcsLogUi; +import git4idea.repo.GitRepositoryManager; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public class DeepComparatorHolder implements Disposable { + + @NotNull private final Project myProject; + @NotNull private final GitRepositoryManager myRepositoryManager; + + @NotNull private final Map myComparators; + + // initialized by pico-container + @SuppressWarnings("UnusedDeclaration") + private DeepComparatorHolder(@NotNull Project project, @NotNull GitRepositoryManager repositoryManager) { + myProject = project; + myRepositoryManager = repositoryManager; + myComparators = ContainerUtil.newHashMap(); + Disposer.register(project, this); + } + + @NotNull + public DeepComparator getInstance(@NotNull VcsLogUi ui) { + DeepComparator comparator = myComparators.get(ui); + if (comparator == null) { + comparator = new DeepComparator(myProject, myRepositoryManager, ui, this); + myComparators.put(ui, comparator); + } + return comparator; + } + + @Override + public void dispose() { + myComparators.clear(); + } + +} diff --git a/plugins/git4idea/src/git4idea/branch/DeepCompareAction.java b/plugins/git4idea/src/git4idea/branch/DeepCompareAction.java new file mode 100644 index 000000000000..ddb6f24042c6 --- /dev/null +++ b/plugins/git4idea/src/git4idea/branch/DeepCompareAction.java @@ -0,0 +1,109 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package git4idea.branch; + +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.DumbAwareAction; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.ListPopup; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.util.Consumer; +import com.intellij.util.Function; +import com.intellij.vcs.log.*; +import com.intellij.vcs.log.data.VcsLogBranchFilterImpl; +import com.intellij.vcs.log.ui.filter.BranchFilterPopupComponent; +import org.jetbrains.annotations.NotNull; + +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.util.Collections; + +public class DeepCompareAction extends ToggleAction implements DumbAware { + + @Override + public boolean isSelected(AnActionEvent e) { + Project project = e.getData(CommonDataKeys.PROJECT); + VcsLogUi ui = e.getData(VcsLogDataKeys.VCS_LOG_UI); + if (project == null || ui == null) { + return false; + } + return DeepComparator.getInstance(project, ui).hasHighlightingOrInProgress(); + } + + @Override + public void setSelected(AnActionEvent e, boolean selected) { + Project project = e.getData(CommonDataKeys.PROJECT); + final VcsLogUi ui = e.getData(VcsLogDataKeys.VCS_LOG_UI); + final VcsLogDataProvider dataProvider = e.getData(VcsLogDataKeys.VCS_LOG_DATA_PROVIDER); + if (project == null || ui == null || dataProvider == null) { + return; + } + final DeepComparator dc = DeepComparator.getInstance(project, ui); + if (selected) { + VcsLogBranchFilter branchFilter = ui.getFilterUi().getFilters().getBranchFilter(); + if (branchFilter == null || branchFilter.getBranchNames().size() != 1) { + selectBranchAndPerformAction(ui.getDataPack(), e, new Consumer() { + @Override + public void consume(String selectedBranch) { + ui.getFilterUi().setFilter(new VcsLogBranchFilterImpl(ui.getDataPack().getRefs().getBranches(), + Collections.singleton(selectedBranch))); + dc.highlightInBackground(selectedBranch, dataProvider); + } + }); + return; + } + String branchToCompare = branchFilter.getBranchNames().iterator().next(); + dc.highlightInBackground(branchToCompare, dataProvider); + } + else { + dc.stopAndUnhighlight(); + } + } + + private static void selectBranchAndPerformAction(@NotNull VcsLogDataPack dataPack, @NotNull AnActionEvent event, + @NotNull final Consumer consumer) { + ActionGroup actionGroup = BranchFilterPopupComponent.constructActionGroup(dataPack, null, new Function() { + @Override + public AnAction fun(final String s) { + return new DumbAwareAction(s) { + @Override + public void actionPerformed(AnActionEvent e) { + consumer.consume(s); + } + }; + } + }); + ListPopup popup = JBPopupFactory.getInstance().createActionGroupPopup("Select branch to compare", actionGroup, event.getDataContext(), + false, false, false, null, -1, null); + InputEvent inputEvent = event.getInputEvent(); + if (inputEvent instanceof MouseEvent) { + popup.show(new RelativePoint((MouseEvent)inputEvent)); + } + else { + popup.showInBestPositionFor(event.getDataContext()); + } + } + + @Override + public void update(AnActionEvent e) { + super.update(e); + VcsLogUi ui = e.getData(VcsLogDataKeys.VCS_LOG_UI); + e.getPresentation().setEnabledAndVisible(ui != null); + } + +} diff --git a/plugins/git4idea/src/git4idea/commands/GitCommand.java b/plugins/git4idea/src/git4idea/commands/GitCommand.java index 226d663beb1f..27beb50100c1 100644 --- a/plugins/git4idea/src/git4idea/commands/GitCommand.java +++ b/plugins/git4idea/src/git4idea/commands/GitCommand.java @@ -41,6 +41,7 @@ public class GitCommand { public static final GitCommand CHECK_ATTR = read("check-attr"); public static final GitCommand COMMIT = write("commit"); public static final GitCommand CONFIG = read("config"); + public static final GitCommand CHERRY = read("cherry"); public static final GitCommand CHERRY_PICK = write("cherry-pick"); public static final GitCommand CLONE = write("clone"); public static final GitCommand DIFF = read("diff"); From ff002dedc7fb05189b89b57e146d4a82c1c5a3ba Mon Sep 17 00:00:00 2001 From: Erokhin Stanislav Date: Tue, 4 Mar 2014 16:21:00 +0400 Subject: [PATCH 25/32] [log] Remake VcsLogJoiner without recursion. --- .../intellij/vcs/log/data/VcsLogJoiner.java | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java index 1a4c81ad3662..43dd771f60a0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogJoiner.java @@ -208,54 +208,55 @@ public class VcsLogJoiner { /*package*/ static class NewCommitIntegrator { private final List list; private final Map newCommitsMap; - private final Collection newCommits; + + private final Stack commitsStack; public NewCommitIntegrator(@NotNull List list, @NotNull Collection newCommits) { this.list = list; newCommitsMap = ContainerUtil.newHashMap(); - this.newCommits = newCommits; for (Commit commit : newCommits) { newCommitsMap.put(commit.getHash(), commit); } + commitsStack = new Stack(); } - // return insert Index - private void insertToList(@NotNull Commit commit) { - if (!newCommitsMap.containsKey(commit.getHash())) { - throw new IllegalStateException("Commit was inserted, but insert call again. Commit hash: " + commit.getHash()); - } - //insert all parents commits - for (Hash parentHash : commit.getParents()) { - Commit parentCommit = newCommitsMap.get(parentHash); - if (parentCommit != null) { - insertToList(parentCommit); - } - } + private void insertAllUseStack() { + while (!newCommitsMap.isEmpty()) { + commitsStack.push(newCommitsMap.values().iterator().next()); + while (!commitsStack.isEmpty()) { + Commit currentCommit = commitsStack.peek(); + boolean allParentsWereAdded = true; + for (Hash parentHash : currentCommit.getParents()) { + Commit parentCommit = newCommitsMap.get(parentHash); + if (parentCommit != null) { + commitsStack.push(parentCommit); + allParentsWereAdded = false; + break; + } + } - int insertIndex; - HashSet parents = new HashSet(commit.getParents()); - for (insertIndex = 0; insertIndex < list.size(); insertIndex++) { - Commit currentCommit = list.get(insertIndex); - if (parents.contains(currentCommit.getHash())) - break; - if (currentCommit.getTime() < commit.getTime()) - break; - } + if (!allParentsWereAdded) + continue; - list.add(insertIndex, commit); - newCommitsMap.remove(commit.getHash()); - } + int insertIndex; + HashSet parents = new HashSet(currentCommit.getParents()); + for (insertIndex = 0; insertIndex < list.size(); insertIndex++) { + Commit someCommit = list.get(insertIndex); + if (parents.contains(someCommit.getHash())) + break; + if (someCommit.getTime() < currentCommit.getTime()) + break; + } - private void insertAllCommits() { - for (Commit commit : newCommits) { - if (newCommitsMap.get(commit.getHash()) != null) { - insertToList(commit); + list.add(insertIndex, currentCommit); + newCommitsMap.remove(currentCommit.getHash()); + commitsStack.pop(); } } } public List getResultList() { - insertAllCommits(); + insertAllUseStack(); return list; } } From 8ce415d40e970d33d735d4485ff24ac5e08dff6b Mon Sep 17 00:00:00 2001 From: Erokhin Stanislav Date: Mon, 10 Mar 2014 20:01:36 +0400 Subject: [PATCH 26/32] [log] Fix tests. (fix wrong line separators) --- .../intellij/vcs/log/newgraph/AbstractTestWithTextFile.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/newgraph/AbstractTestWithTextFile.java b/platform/vcs-log/graph/test/com/intellij/vcs/log/newgraph/AbstractTestWithTextFile.java index 49382c22caed..e09defcd68c9 100644 --- a/platform/vcs-log/graph/test/com/intellij/vcs/log/newgraph/AbstractTestWithTextFile.java +++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/newgraph/AbstractTestWithTextFile.java @@ -33,8 +33,8 @@ public abstract class AbstractTestWithTextFile { } protected void doTest(String testName) throws IOException { - String in = FileUtil.loadFile(new File(myDirectory + testName + IN_POSTFIX)); - String out = FileUtil.loadFile(new File(myDirectory + testName + OUT_POSTFIX)); + String in = FileUtil.loadFile(new File(myDirectory + testName + IN_POSTFIX), true); + String out = FileUtil.loadFile(new File(myDirectory + testName + OUT_POSTFIX), true); runTest(in, out); } From 8c56a6bfad9b2eda88091ba9ff3a318e0829cbe0 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Mon, 10 Mar 2014 21:38:29 +0400 Subject: [PATCH 27/32] github tests with wrong notifications fixed --- .../testSrc/com/intellij/openapi/vcs/TestVcsNotifier.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/TestVcsNotifier.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/TestVcsNotifier.java index fabf2f2e9b44..6fe9eb1e23dd 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/TestVcsNotifier.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/TestVcsNotifier.java @@ -37,6 +37,7 @@ public class TestVcsNotifier extends VcsNotifier { return myLastNotification; } + @Override @NotNull public Notification notify(@NotNull NotificationGroup notificationGroup, @NotNull String title, @NotNull String message, @NotNull NotificationType type, @Nullable NotificationListener listener) { @@ -44,6 +45,11 @@ public class TestVcsNotifier extends VcsNotifier { return myLastNotification; } + @Override + public void notify(@NotNull Notification notification) { + myLastNotification = notification; + } + public void cleanup() { myLastNotification = null; } From 965aafa85523d3d3e685ba83f15e6c265631005e Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 10 Mar 2014 18:42:35 +0100 Subject: [PATCH 28/32] for unsaved documents with committed state and psi backed index use the same logic as for unsaved documents with plain index --- .../intellij/psi/stubs/StubTreeBuilder.java | 15 ++++---- .../util/indexing/FileBasedIndexImpl.java | 38 ++++++++++++------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java index 871b7ee3d4dd..d69e62cff2ce 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java @@ -58,17 +58,18 @@ public class StubTreeBuilder { final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType(); PsiFile psi = null; - CharSequence contentAsText = null; + CharSequence contentAsText = inputData.getContentAsText(); Document document = FileDocumentManager.getInstance().getCachedDocument(inputData.getFile()); if (document != null) { - PsiFile existingPsi = PsiDocumentManager.getInstance(inputData.getProject()).getPsiFile(document); - if (existingPsi != null) { - contentAsText = existingPsi.getText(); - psi = existingPsi; + PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(inputData.getProject()); + if (psiDocumentManager.isUncommited(document)) { + PsiFile existingPsi = psiDocumentManager.getPsiFile(document); + if(existingPsi != null) { + psi = existingPsi; + } } } - if (contentAsText == null) { - contentAsText = inputData.getContentAsText(); + if (psi == null) { psi = inputData.getPsiFile(); } psi = psi.getViewProvider().getStubBindingRoot(); 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 4b1190d5d9cb..5a812ce2ae7b 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -1420,7 +1420,11 @@ public class FileBasedIndexImpl extends FileBasedIndex { return; // no need to index unsaved docs } - Set documents = myPsiDependentIndices.contains(indexId) ? getTransactedDocuments() : getUnsavedDocuments(); + Set documents = getUnsavedDocuments(); + boolean psiBasedIndex = myPsiDependentIndices.contains(indexId); + if(psiBasedIndex) { + documents.addAll(getTransactedDocuments()); + } if (!documents.isEmpty()) { // now index unsaved data @@ -1434,6 +1438,9 @@ public class FileBasedIndexImpl extends FileBasedIndex { boolean allDocsProcessed = true; try { for (Document document : documents) { + if (psiBasedIndex && project != null && PsiDocumentManager.getInstance(project).isUncommited(document)) { + continue; + } allDocsProcessed &= indexUnsavedDocument(document, indexId, project, filter, restrictedFile); ProgressManager.checkCanceled(); } @@ -1451,9 +1458,6 @@ public class FileBasedIndexImpl extends FileBasedIndex { ProgressManager.checkCanceled(); // assume all tasks were finished or cancelled in the same time // safe to set the flag here, because it will be cleared under the WriteAction - - // if we have uncommitted documents in unsaved documents, we may index old psi with new uncommitted doc, - // to properly reindex with new psi / new doc we don't mark index up to date in this case (IDEA-111448) myUpToDateIndices.add(indexId); } } @@ -2505,17 +2509,25 @@ public class FileBasedIndexImpl extends FileBasedIndex { PsiFile file = event.getFile(); if (file != null) { VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile instanceof VirtualFileWithId) { - boolean wasIndexed = false; + FileDocumentManager instance = FileDocumentManager.getInstance(); + Document document = instance.getDocument(virtualFile); + if (document != null && instance.isDocumentUnsaved(document)) { for(ID psiBackedIndex:myPsiDependentIndices) { - if (isFileIndexed(virtualFile, psiBackedIndex)) { - IndexingStamp.update(virtualFile, psiBackedIndex, IndexInfrastructure.INVALID_STAMP2); - wasIndexed = true; - } + myUpToDateIndices.remove(psiBackedIndex); } - if (wasIndexed) { - myChangedFilesCollector.scheduleForUpdate(virtualFile); - IndexingStamp.flushCache(virtualFile); + } else { // change in persistent file + if (virtualFile instanceof VirtualFileWithId) { + boolean wasIndexed = false; + for (ID psiBackedIndex : myPsiDependentIndices) { + if (isFileIndexed(virtualFile, psiBackedIndex)) { + IndexingStamp.update(virtualFile, psiBackedIndex, IndexInfrastructure.INVALID_STAMP2); + wasIndexed = true; + } + } + if (wasIndexed) { + myChangedFilesCollector.scheduleForUpdate(virtualFile); + IndexingStamp.flushCache(virtualFile); + } } } } From c60c03873b6442875a47666f3c89256800839a2e Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Mon, 10 Mar 2014 21:51:25 +0400 Subject: [PATCH 29/32] style: remove unnecessary method --- .../testSrc/com/intellij/openapi/vcs/TestVcsNotifier.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/TestVcsNotifier.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/TestVcsNotifier.java index 6fe9eb1e23dd..d69395e7437a 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/TestVcsNotifier.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/TestVcsNotifier.java @@ -45,11 +45,6 @@ public class TestVcsNotifier extends VcsNotifier { return myLastNotification; } - @Override - public void notify(@NotNull Notification notification) { - myLastNotification = notification; - } - public void cleanup() { myLastNotification = null; } From ffa6350613c27a457081fcf059dd29a8b45063a3 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 10 Mar 2014 19:01:15 +0100 Subject: [PATCH 30/32] enable new nashorn variables view by default --- .../impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java index ca015a9929b2..dc80f8b139af 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/VariablesPanel.java @@ -75,7 +75,7 @@ public class VariablesPanel extends DebuggerTreePanel implements DataProvider { @Override protected DebuggerTree createTreeView() { - return new FrameVariablesTree(getProject(), SystemProperties.getBooleanProperty("java.debugger.xTree", false) ? this : null); + return new FrameVariablesTree(getProject(), SystemProperties.getBooleanProperty("java.debugger.xTree", true) ? this : null); } @Override From 5e7118077104adcff04d096ad126c7d2430f11c9 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 10 Mar 2014 17:30:36 +0100 Subject: [PATCH 31/32] add a proxy test that fails on java 8 --- .../com/intellij/util/xml/ProxyTest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/xml/dom-tests/tests/com/intellij/util/xml/ProxyTest.java b/xml/dom-tests/tests/com/intellij/util/xml/ProxyTest.java index bf3b3d43ce13..ab29e587c0e7 100644 --- a/xml/dom-tests/tests/com/intellij/util/xml/ProxyTest.java +++ b/xml/dom-tests/tests/com/intellij/util/xml/ProxyTest.java @@ -1,6 +1,7 @@ package com.intellij.util.xml; import com.intellij.util.ArrayUtil; +import com.intellij.util.xml.ui.DomUIFactory; import junit.framework.TestCase; import net.sf.cglib.proxy.AdvancedProxy; import net.sf.cglib.proxy.InvocationHandler; @@ -167,5 +168,26 @@ public class ProxyTest extends TestCase { assertEquals(((CovariantFromBaseClassTest.Intf)proxy).sayA(), "a"); } + public void testGenericMethodInvocationJava8() throws Throwable { + ConcreteInterface proxy = AdvancedProxy.createProxy(new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return 42; + } + }, null, ConcreteInterface.class); + Method foo = DomUIFactory.findMethod(GenericInterface.class, "foo"); + assert foo != null; + assertEquals(42, proxy.foo("a")); + assertEquals(42, foo.invoke(proxy, "a")); + } + + interface GenericInterface { + Object foo(T t); + } + + interface ConcreteInterface extends GenericInterface { + Object foo(String t); + } + } From e5d9dff7c04be337e14d1d4b377507a83e610b5a Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 10 Mar 2014 18:38:42 +0100 Subject: [PATCH 32/32] add -> keyword to cpp and make sure it's lexed correctly (IDEA-121906) --- .../src/CommunityFileTypes.xml | 1 + .../completion/HippieCompletionTest.groovy | 9 +++++++ .../custom/CustomFileTypeLexer.java | 2 +- .../custom/tokens/IdentifierParser.java | 13 ++++++---- .../custom/tokens/KeywordParser.java | 25 +++++++++++-------- .../src/FileTypeManager.xml | 1 + .../custom/CustomFileTypeLexerTest.groovy | 10 ++++++++ 7 files changed, 45 insertions(+), 16 deletions(-) diff --git a/community-resources/src/CommunityFileTypes.xml b/community-resources/src/CommunityFileTypes.xml index e15ce6cff542..b46643afa562 100644 --- a/community-resources/src/CommunityFileTypes.xml +++ b/community-resources/src/CommunityFileTypes.xml @@ -60,6 +60,7 @@ + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy index 4cad78b0c467..7de79b533944 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy @@ -189,7 +189,16 @@ class Xoo { class Xoo { } ''' + } + public void "test cpp indirection"() { + myFixture.configureByText "a.c", '''f +foo->bar +''' + complete() + myFixture.checkResult '''foo +foo->bar +''' } private void complete() { diff --git a/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/CustomFileTypeLexer.java b/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/CustomFileTypeLexer.java index da784dfbad22..d253ace0930c 100644 --- a/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/CustomFileTypeLexer.java +++ b/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/CustomFileTypeLexer.java @@ -50,7 +50,7 @@ public final class CustomFileTypeLexer extends AbstractCustomLexer { } }; - final IdentifierParser identifierParser = new IdentifierParser(); + final IdentifierParser identifierParser = new IdentifierParser(parser); final QuotedStringParser quotedStringParser = new QuotedStringParser("\"", CustomHighlighterTokenType.STRING, table.isHasStringEscapes()); diff --git a/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/IdentifierParser.java b/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/IdentifierParser.java index 57b29ae806a8..8fc92e722e0f 100644 --- a/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/IdentifierParser.java +++ b/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/IdentifierParser.java @@ -23,7 +23,10 @@ import com.intellij.psi.tree.IElementType; * @author dsl */ public class IdentifierParser extends TokenParser { - public IdentifierParser() { + private final KeywordParser myKeywordParser; + + public IdentifierParser(KeywordParser keywordParser) { + myKeywordParser = keywordParser; } @Override @@ -31,15 +34,15 @@ public class IdentifierParser extends TokenParser { if (!Character.isJavaIdentifierStart(myBuffer.charAt(position))) return false; final int start = position; for (position++; position < myEndOffset; position++) { - final char c = myBuffer.charAt(position); - if (!isIdentifierPart(c)) break; + if (!isIdentifierPart(position)) break; } IElementType tokenType = CustomHighlighterTokenType.IDENTIFIER; myTokenInfo.updateData(start, position, tokenType); return true; } - protected boolean isIdentifierPart(final char c) { - return Character.isJavaIdentifierPart(c) || c == '-'; + private boolean isIdentifierPart(int position) { + if (myBuffer.charAt(position) == '-') return !myKeywordParser.hasToken(position, myBuffer, null); + return KeywordParser.isWordPart(position, myBuffer); } } diff --git a/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java b/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java index f45032c23f05..b210305c2489 100644 --- a/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java +++ b/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java @@ -23,6 +23,7 @@ import com.intellij.psi.tree.IElementType; import com.intellij.util.containers.CharTrie; import gnu.trove.THashSet; import gnu.trove.TIntHashSet; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -63,10 +64,9 @@ public class KeywordParser { return result; } - public boolean hasToken(int position, CharSequence myBuffer, TokenInfo myTokenInfo) { + public boolean hasToken(int position, CharSequence myBuffer, @Nullable TokenInfo tokenInfo) { int index = 0; int offset = position; - boolean found = false; while (offset < myBuffer.length()) { char c = myBuffer.charAt(offset++); int nextIndex = myTrie.findSubNode(index, myIgnoreCase ? Character.toUpperCase(c) : c); @@ -79,24 +79,29 @@ public class KeywordParser { String testKeyword = myIgnoreCase ? StringUtil.toUpperCase(keyword) : keyword; for (int i = 0; i < CustomHighlighterTokenType.KEYWORD_TYPE_COUNT; i++) { if (myKeywordSets.get(i).contains(testKeyword)) { - myTokenInfo.updateData(position, position + keyword.length(), getToken(i)); - found = true; - break; + if (tokenInfo != null) { + tokenInfo.updateData(position, position + keyword.length(), getToken(i)); + } + return true; } } } } - return found; + return false; } - private static boolean isWordEnd(int offset, CharSequence myBuffer) { - if (offset == myBuffer.length()) { + private static boolean isWordEnd(int offset, CharSequence sequence) { + if (offset == sequence.length()) { return true; } + + return !isWordPart(offset - 1, sequence) || !isWordPart(offset, sequence); + } - char ch = myBuffer.charAt(offset); - return ch != '-' && ch != '_' && !Character.isLetterOrDigit(ch); + static boolean isWordPart(int offset, CharSequence sequence) { + char ch = sequence.charAt(offset); + return ch == '-' || Character.isJavaIdentifierPart(ch); } private static IElementType getToken(int keywordSetIndex) { diff --git a/platform/platform-resources/src/FileTypeManager.xml b/platform/platform-resources/src/FileTypeManager.xml index a381b19a9a5f..2a643ddc1661 100644 --- a/platform/platform-resources/src/FileTypeManager.xml +++ b/platform/platform-resources/src/FileTypeManager.xml @@ -60,6 +60,7 @@ + diff --git a/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeLexerTest.groovy b/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeLexerTest.groovy index 0ac9a1e03cbf..7f13b49765c9 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeLexerTest.groovy +++ b/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeLexerTest.groovy @@ -283,6 +283,16 @@ IDENTIFIER ('k') ''' } + public void testCpp() { + SyntaxTable table = new SyntaxTable() + table.addKeyword1('->') + doTest table, "foo->bar", '''\ +IDENTIFIER ('foo') +KEYWORD_1 ('->') +IDENTIFIER ('bar') +''' + } + public void testNumber() { doTest createPropTable(), "1.23=1.24", '''\ NUMBER ('1.23')