diff --git a/bin/WinLauncher/WinLauncher.exe b/bin/WinLauncher/WinLauncher.exe index 66b04fa1bfd8..afe000ae7459 100644 Binary files a/bin/WinLauncher/WinLauncher.exe and b/bin/WinLauncher/WinLauncher.exe differ diff --git a/bin/WinLauncher/WinLauncher64.exe b/bin/WinLauncher/WinLauncher64.exe index 12a18522deed..7dc6ef8deb5e 100644 Binary files a/bin/WinLauncher/WinLauncher64.exe and b/bin/WinLauncher/WinLauncher64.exe differ diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java index ce375815bb77..0f5398a56cba 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/AdjustArrayRangeAction.java @@ -16,6 +16,7 @@ package com.intellij.debugger.actions; import com.intellij.debugger.engine.DebugProcessImpl; +import com.intellij.debugger.engine.JavaValue; import com.intellij.debugger.engine.events.SuspendContextCommandImpl; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.settings.ArrayRendererConfigurable; @@ -27,6 +28,9 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; +import com.intellij.xdebugger.frame.XValue; +import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.Nullable; public class AdjustArrayRangeAction extends DebuggerAction { @@ -44,42 +48,48 @@ public class AdjustArrayRangeAction extends DebuggerAction { final Project project = debuggerContext.getProject(); - final DebuggerTreeNodeImpl selectedNode = getSelectedNode(e.getDataContext()); - if (selectedNode == null) { - return; - } - NodeDescriptorImpl descriptor = selectedNode.getDescriptor(); - if(!(descriptor instanceof ValueDescriptorImpl /*&& ((ValueDescriptorImpl)descriptor).isArray()*/)) { + final XValueNodeImpl node = XDebuggerTreeActionBase.getSelectedNode(e.getDataContext()); + if (node == null) { return; } - final ArrayRenderer renderer = getArrayRenderer((ValueDescriptorImpl)descriptor)/*(ArrayRenderer)((ValueDescriptorImpl)selectedNode.getDescriptor()).getLastRenderer()*/; + XValue container = node.getValueContainer(); + if (!(container instanceof JavaValue)) { + return; + } + + final ValueDescriptorImpl descriptor = ((JavaValue)container).getDescriptor(); + ArrayRenderer renderer = getArrayRenderer(descriptor); if (renderer == null) { return; } - String title = createNodeTitle("", selectedNode); - String label = selectedNode.toString(); - int index = label.indexOf('='); - if (index > 0) { - title = title + " " + label.substring(index); - } + //String title = createNodeTitle("", selectedNode); + //String label = selectedNode.toString(); + //int index = label.indexOf('='); + //if (index > 0) { + // title = title + " " + label.substring(index); + //} + String title = node.getName(); final ArrayRenderer clonedRenderer = renderer.clone(); + clonedRenderer.setForced(true); if (ShowSettingsUtil.getInstance().editConfigurable(project, new NamedArrayConfigurable(title, clonedRenderer))) { debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(debuggerContext.getSuspendContext()) { @Override public void contextAction() throws Exception { - final ValueDescriptorImpl nodeDescriptor = (ValueDescriptorImpl)selectedNode.getDescriptor(); - final Renderer lastRenderer = nodeDescriptor.getLastRenderer(); + final Renderer lastRenderer = descriptor.getLastRenderer(); if (lastRenderer instanceof ArrayRenderer) { - selectedNode.setRenderer(clonedRenderer); + descriptor.setRenderer(clonedRenderer); + refreshViews(node); + //selectedNode.setRenderer(clonedRenderer); } else if (lastRenderer instanceof CompoundNodeRenderer) { final CompoundNodeRenderer compoundRenderer = (CompoundNodeRenderer)lastRenderer; final ChildrenRenderer childrenRenderer = compoundRenderer.getChildrenRenderer(); if (childrenRenderer instanceof ExpressionChildrenRenderer) { - ExpressionChildrenRenderer.setPreferableChildrenRenderer(nodeDescriptor, clonedRenderer); - selectedNode.calcRepresentation(); + ExpressionChildrenRenderer.setPreferableChildrenRenderer(descriptor, clonedRenderer); + refreshViews(node); + //selectedNode.calcRepresentation(); } } } @@ -90,10 +100,14 @@ public class AdjustArrayRangeAction extends DebuggerAction { @Override public void update(AnActionEvent e) { boolean enable = false; - DebuggerTreeNodeImpl selectedNode = getSelectedNode(e.getDataContext()); - if(selectedNode != null) { - NodeDescriptorImpl descriptor = selectedNode.getDescriptor(); - enable = descriptor instanceof ValueDescriptorImpl && getArrayRenderer((ValueDescriptorImpl)descriptor) != null; + XValueNodeImpl node = XDebuggerTreeActionBase.getSelectedNode(e.getDataContext()); + if (node == null) { + return; + } + XValue container = node.getValueContainer(); + if (container instanceof JavaValue) { + ValueDescriptorImpl descriptor = ((JavaValue)container).getDescriptor(); + enable = getArrayRenderer(descriptor) != null; } e.getPresentation().setVisible(enable); } diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/DebuggerAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/DebuggerAction.java index 86ddfaa5fc08..b369a25e2e09 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/DebuggerAction.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/DebuggerAction.java @@ -22,6 +22,7 @@ package com.intellij.debugger.actions; import com.intellij.debugger.DebuggerManagerEx; +import com.intellij.debugger.engine.JavaDebugProcess; import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.impl.DebuggerStateManager; import com.intellij.debugger.ui.impl.DebuggerTreePanel; @@ -32,6 +33,10 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; import com.intellij.ui.DoubleClickListener; +import com.intellij.xdebugger.XDebugProcess; +import com.intellij.xdebugger.XDebugSession; +import com.intellij.xdebugger.impl.frame.XDebugView; +import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -153,4 +158,15 @@ public abstract class DebuggerAction extends AnAction { } }); } + + public static void refreshViews(XValueNodeImpl node) { + final XDebugSession session = XDebugView.getSession(node.getTree()); + if (session != null) { + XDebugProcess process = session.getDebugProcess(); + if (process instanceof JavaDebugProcess) { + ((JavaDebugProcess)process).saveNodeHistory(); + } + session.rebuildViews(); + } + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.java b/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.java index bd8efab637ac..fd0d8f6785b3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.java @@ -22,13 +22,11 @@ import com.intellij.debugger.impl.DebuggerContextImpl; import com.intellij.debugger.settings.NodeRendererSettings; import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl; import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl; -import com.intellij.debugger.ui.tree.render.DescriptorLabelListener; import com.intellij.debugger.ui.tree.render.NodeRenderer; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbAware; import com.intellij.xdebugger.frame.XValue; -import com.intellij.xdebugger.frame.XValuePlace; import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase; import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl; import org.jetbrains.annotations.NotNull; @@ -66,7 +64,7 @@ public class ViewAsGroup extends ActionGroup implements DumbAware { } XValue container = node.getValueContainer(); if (container instanceof JavaValue) { - if (((ValueDescriptorImpl)((JavaValue)container).getDescriptor()).getLastRenderer() != myNodeRenderer) { + if (((JavaValue)container).getDescriptor().getLastRenderer() != myNodeRenderer) { return false; } } @@ -83,11 +81,12 @@ public class ViewAsGroup extends ActionGroup implements DumbAware { public void threadAction() { XValue container = node.getValueContainer(); if (container instanceof JavaValue) { - final ValueDescriptorImpl valueDescriptor = (ValueDescriptorImpl)((JavaValue)container).getDescriptor(); + final ValueDescriptorImpl valueDescriptor = ((JavaValue)container).getDescriptor(); if (state) { valueDescriptor.setRenderer(myNodeRenderer); - valueDescriptor.updateRepresentation(debuggerContext.createEvaluationContext(), DescriptorLabelListener.DUMMY_LISTENER); - container.computePresentation(node, XValuePlace.TREE); + DebuggerAction.refreshViews(node); + //valueDescriptor.updateRepresentation(debuggerContext.createEvaluationContext(), DescriptorLabelListener.DUMMY_LISTENER); + //container.computePresentation(node, XValuePlace.TREE); } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java index 37ee00b94eaf..34b18bbc4da7 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaDebugProcess.java @@ -18,20 +18,18 @@ package com.intellij.debugger.engine; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.actions.DebuggerActions; import com.intellij.debugger.engine.evaluation.EvaluationContext; -import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; import com.intellij.debugger.engine.events.DebuggerCommandImpl; import com.intellij.debugger.engine.events.DebuggerContextCommandImpl; import com.intellij.debugger.impl.*; +import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.settings.DebuggerSettings; import com.intellij.debugger.ui.DebuggerContentInfo; import com.intellij.debugger.ui.breakpoints.Breakpoint; import com.intellij.debugger.ui.impl.ThreadsPanel; import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl; import com.intellij.debugger.ui.impl.watch.MessageDescriptor; -import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl; import com.intellij.debugger.ui.impl.watch.NodeManagerImpl; import com.intellij.debugger.ui.tree.NodeDescriptor; -import com.intellij.debugger.ui.tree.render.DescriptorLabelListener; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.ui.ExecutionConsole; import com.intellij.execution.ui.ExecutionConsoleEx; @@ -150,29 +148,40 @@ public class JavaDebugProcess extends XDebugProcess { }; session.addSessionListener(new XDebugSessionAdapter() { @Override - public void beforeSessionResume() { - myJavaSession.getProcess().getManagerThread().schedule(new DebuggerCommandImpl() { - @Override - protected void action() throws Exception { - myNodeManager.setHistoryByContext(getDebuggerStateManager().getContext()); - } - @Override - public Priority getPriority() { - return Priority.NORMAL; - } - }); + public void sessionPaused() { + saveNodeHistory(); } @Override public void stackFrameChanged() { XStackFrame frame = session.getCurrentStackFrame(); if (frame instanceof JavaStackFrame) { - DebuggerContextUtil.setStackFrame(javaSession.getContextManager(), ((JavaStackFrame)frame).getStackFrameProxy()); + StackFrameProxyImpl frameProxy = ((JavaStackFrame)frame).getStackFrameProxy(); + DebuggerContextUtil.setStackFrame(javaSession.getContextManager(), frameProxy); + saveNodeHistory(frameProxy); } } }); } + public void saveNodeHistory() { + saveNodeHistory(getDebuggerStateManager().getContext().getFrameProxy()); + } + + private void saveNodeHistory(final StackFrameProxyImpl frameProxy) { + myJavaSession.getProcess().getManagerThread().invoke(new DebuggerCommandImpl() { + @Override + protected void action() throws Exception { + myNodeManager.setHistoryByContext(frameProxy); + } + + @Override + public Priority getPriority() { + return Priority.NORMAL; + } + }); + } + private DebuggerStateManager getDebuggerStateManager() { return myJavaSession.getContextManager(); } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java index fd3a15bd8943..85957cb2120a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java @@ -103,6 +103,7 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV } @Override + @NotNull public ValueDescriptorImpl getDescriptor() { return myValueDescriptor; } diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java index 8408364f7e73..f36c9f14cee6 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerContextUtil.java @@ -23,11 +23,12 @@ import com.intellij.debugger.jdi.StackFrameProxyImpl; import com.intellij.debugger.ui.impl.watch.ThreadDescriptorImpl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; -import com.intellij.psi.util.PsiUtilBase; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XSourcePosition; import org.jetbrains.annotations.NotNull; @@ -75,7 +76,9 @@ public class DebuggerContextUtil { final XDebugSession debugSession = session.getXDebugSession(); if (debugSession != null) { final XSourcePosition position = debugSession.getCurrentPosition(); - final Editor editor = PsiUtilBase.findEditor(psi); + Editor editor = ((FileEditorManagerImpl)FileEditorManager.getInstance(file.getProject())).getSelectedTextEditor(true); + + //final Editor editor = fileEditor instanceof TextEditorImpl ? ((TextEditorImpl)fileEditor).getEditor() : null; if (editor != null && position != null && file.getVirtualFile().equals(position.getFile())) { final Couple> usages = IdentifierHighlighterPass.getHighlightUsages(psi, file); final List ranges = new ArrayList(); diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java index 0a5210f16c36..2c515f2302a9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java @@ -199,6 +199,7 @@ public class DebuggerSession implements AbstractDebuggerSession { ValueLookupManager.getInstance(getProject()).startListening(); } + @NotNull public DebuggerStateManager getContextManager() { return myContextManager; } diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java index 452a924aed00..8785e687eff3 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java @@ -53,7 +53,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { private JCheckBox myCbShowObjectId; private StateRestoringCheckBox myCbShowStaticFinalFields; - private final ArrayRendererConfigurable myArrayRendererConfigurable; + //private final ArrayRendererConfigurable myArrayRendererConfigurable; private JCheckBox myCbEnableAlternateViews; private JCheckBox myCbEnableToString; @@ -66,12 +66,12 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { public DebuggerDataViewsConfigurable(@Nullable Project project) { myProject = project; - myArrayRendererConfigurable = new ArrayRendererConfigurable(NodeRendererSettings.getInstance().getArrayRenderer()); + //myArrayRendererConfigurable = new ArrayRendererConfigurable(NodeRendererSettings.getInstance().getArrayRenderer()); } @Override public void disposeUIResources() { - myArrayRendererConfigurable.disposeUIResources(); + //myArrayRendererConfigurable.disposeUIResources(); myToStringFilterEditor = null; myProject = null; } @@ -165,13 +165,14 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { panel.add(showPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(4, 0, 0, 0), 0, 0)); - final JPanel arraysPanel = new JPanel(new BorderLayout(0, UIUtil.DEFAULT_VGAP)); - final JComponent arraysComponent = myArrayRendererConfigurable.createComponent(); - assert arraysComponent != null; - arraysPanel.add(arraysComponent, BorderLayout.CENTER); - arraysPanel.add(myCbHideNullArrayElements, BorderLayout.SOUTH); - arraysPanel.setBorder(IdeBorderFactory.createTitledBorder("Arrays", true)); - panel.add(arraysPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + //final JPanel arraysPanel = new JPanel(new BorderLayout(0, UIUtil.DEFAULT_VGAP)); + //final JComponent arraysComponent = myArrayRendererConfigurable.createComponent(); + //assert arraysComponent != null; + //arraysPanel.add(arraysComponent, BorderLayout.CENTER); + //arraysPanel.add(myCbHideNullArrayElements, BorderLayout.SOUTH); + //arraysPanel.setBorder(IdeBorderFactory.createTitledBorder("Arrays", true)); + //panel.add(arraysPanel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); + panel.add(myCbHideNullArrayElements, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); panel.add(myCbEnableAlternateViews, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 0, 0, 10), 0, 0)); // starting 4-th row @@ -209,7 +210,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { myAutoTooltip.save(); - myArrayRendererConfigurable.apply(); + //myArrayRendererConfigurable.apply(); rendererSettings.fireRenderersChanged(); } @@ -250,7 +251,7 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { myRbFromList.setEnabled(toStringEnabled); myRbAllThatOverride.setEnabled(toStringEnabled); - myArrayRendererConfigurable.reset(); + //myArrayRendererConfigurable.reset(); } @Override @@ -266,9 +267,9 @@ public class DebuggerDataViewsConfigurable implements SearchableConfigurable { } private boolean areDefaultRenderersModified() { - if (myArrayRendererConfigurable.isModified()) { - return true; - } + //if (myArrayRendererConfigurable.isModified()) { + // return true; + //} final NodeRendererSettings rendererSettings = NodeRendererSettings.getInstance(); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorFactoryImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorFactoryImpl.java index 3455672fa4dc..0a94548338d4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorFactoryImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorFactoryImpl.java @@ -93,6 +93,10 @@ public class NodeDescriptorFactoryImpl implements NodeDescriptorFactory { } public void deriveHistoryTree(DescriptorTree tree, final StackFrameContext context) { + deriveHistoryTree(tree, context.getFrameProxy()); + } + + public void deriveHistoryTree(DescriptorTree tree, final StackFrameProxy frameProxy) { final MarkedDescriptorTree descriptorTree = new MarkedDescriptorTree(); final MarkedDescriptorTree displayDescriptorTree = new MarkedDescriptorTree(); @@ -109,13 +113,12 @@ public class NodeDescriptorFactoryImpl implements NodeDescriptorFactory { myDescriptorSearcher = new DescriptorTreeSearcher(descriptorTree); myDisplayDescriptorSearcher = new DisplayDescriptorTreeSearcher(displayDescriptorTree); - myCurrentHistoryTree = createDescriptorTree(context, tree); + myCurrentHistoryTree = createDescriptorTree(frameProxy, tree); } - private static DescriptorTree createDescriptorTree(final StackFrameContext context, final DescriptorTree fromTree) { + private static DescriptorTree createDescriptorTree(final StackFrameProxy frameProxy, final DescriptorTree fromTree) { int frameCount = -1; int frameIndex = -1; - final StackFrameProxy frameProxy = context.getFrameProxy(); if (frameProxy != null) { try { final ThreadReferenceProxy threadReferenceProxy = frameProxy.threadProxy(); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeManagerImpl.java index 53e820da02fd..b76022122594 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeManagerImpl.java @@ -75,11 +75,15 @@ public class NodeManagerImpl extends NodeDescriptorFactoryImpl implements NodeMa } public void setHistoryByContext(final DebuggerContextImpl context) { + setHistoryByContext(context.getFrameProxy()); + } + + public void setHistoryByContext(StackFrameProxyImpl frameProxy) { if (myHistoryKey != null) { myHistories.put(myHistoryKey, getCurrentHistoryTree()); } - final String historyKey = getContextKey(context.getFrameProxy()); + final String historyKey = getContextKey(frameProxy); final DescriptorTree descriptorTree; if (historyKey != null) { final DescriptorTree historyTree = myHistories.get(historyKey); @@ -89,7 +93,7 @@ public class NodeManagerImpl extends NodeDescriptorFactoryImpl implements NodeMa descriptorTree = new DescriptorTree(true); } - deriveHistoryTree(descriptorTree, context); + deriveHistoryTree(descriptorTree, frameProxy); myHistoryKey = historyKey; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java index 9615aae98233..f7f05fcc496f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ArrayRenderer.java @@ -65,6 +65,8 @@ public class ArrayRenderer extends NodeRendererImpl{ public int ENTRIES_LIMIT = 101; private final static String MORE_ELEMENTS = "..."; + private boolean myForced = false; + public ArrayRenderer() { myProperties.setEnabled(true); } @@ -97,13 +99,19 @@ public class ArrayRenderer extends NodeRendererImpl{ return ClassRenderer.calcLabel(descriptor); } + public void setForced(boolean forced) { + myForced = forced; + } + public void buildChildren(Value value, ChildrenBuilder builder, EvaluationContext evaluationContext) { DebuggerManagerThreadImpl.assertIsManagerThread(); List children = new ArrayList(); NodeManagerImpl nodeManager = (NodeManagerImpl)builder.getNodeManager(); NodeDescriptorFactory descriptorFactory = builder.getDescriptorManager(); - builder.initChildrenArrayRenderer(this); + if (!myForced) { + builder.initChildrenArrayRenderer(this); + } ArrayReference array = (ArrayReference)value; if (array.length() > 0) { @@ -182,7 +190,7 @@ public class ArrayRenderer extends NodeRendererImpl{ // children.add(0, nodeManager.createMessageNode(new MessageDescriptor(MORE_ELEMENTS, MessageDescriptor.SPECIAL))); //} - if(END_INDEX < array.length() - 1) { + if(!myForced && END_INDEX < array.length() - 1) { //children.add(nodeManager.createMessageNode(new MessageDescriptor(MORE_ELEMENTS, MessageDescriptor.SPECIAL))); builder.setRemaining(array.length()-END_INDEX); } diff --git a/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java b/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java index 3d497b829d50..3f087a998304 100644 --- a/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java +++ b/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java @@ -116,7 +116,7 @@ public class ImportModuleAction extends AnAction { if (lastLocation != null) { toSelect = LocalFileSystem.getInstance().refreshAndFindFileByPath(lastLocation); } - VirtualFile[] files = chooser.choose(toSelect, project); + VirtualFile[] files = chooser.choose(project, toSelect); if (files.length == 0) { return null; } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java index 10df2939f6e7..a10265607029 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleEditor.java @@ -206,7 +206,9 @@ public abstract class ModuleEditor implements Place.Navigator, Disposable { myEditors.add(new ModuleConfigurableWrapper(moduleConfigurable)); } for(ModuleConfigurableEP extension : myModule.getExtensions(MODULE_CONFIGURABLES)) { - myEditors.add(new ModuleConfigurableWrapper(extension.createConfigurable())); + if (extension.canCreateConfigurable()) { + myEditors.add(new ModuleConfigurableWrapper(extension.createConfigurable())); + } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java index dbf454207cca..d85fb72894d7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java @@ -403,6 +403,7 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction/*, Hig if (varargParam != null && pi >= parameters.length) return false; PsiType exprType = RefactoringUtil.getTypeByExpression(expression); if (exprType == null) return false; + exprType = GenericsUtil.getVariableTypeByExpressionType(exprType); JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(expression.getProject()); String name = suggestUniqueParameterName(codeStyleManager, expression, exprType, existingNames); final ParameterInfoImpl newParameterInfo = new ParameterInfoImpl(-1, name, exprType, expression.getText().replace('\n', ' ')); diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractDialog.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractDialog.java index 7e49181472b0..9f83b6ed080b 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractDialog.java @@ -20,25 +20,18 @@ */ package com.intellij.refactoring.extractMethod; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; import com.intellij.psi.PsiModifier; import com.intellij.refactoring.util.VariableData; -public abstract class AbstractExtractDialog extends DialogWrapper { - protected AbstractExtractDialog(Project project) { - super(project, true); - } - - - public abstract String getChosenMethodName(); - - public abstract VariableData[] getChosenParameters(); +public interface AbstractExtractDialog { + String getChosenMethodName(); + VariableData[] getChosenParameters(); @PsiModifier.ModifierConstant - public abstract String getVisibility(); + String getVisibility(); + boolean isMakeStatic(); + boolean isChainedConstructor(); - public abstract boolean isMakeStatic(); - - public abstract boolean isChainedConstructor(); + void show(); + boolean isOK(); } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java index f4cfccb496ad..fc933de2b80e 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java @@ -21,6 +21,7 @@ import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.ui.VerticalFlowLayout; import com.intellij.openapi.util.text.StringUtil; @@ -59,7 +60,7 @@ import java.awt.event.*; * @author Konstantin Bulenkov */ @SuppressWarnings("MethodMayBeStatic") -public class ExtractMethodDialog extends AbstractExtractDialog { +public class ExtractMethodDialog extends DialogWrapper implements AbstractExtractDialog { public static final String EXTRACT_METHOD_DEFAULT_VISIBILITY = "extract.method.default.visibility"; private final Project myProject; private final PsiType myReturnType; @@ -96,7 +97,7 @@ public class ExtractMethodDialog extends AbstractExtractDialog { String title, String helpId, final PsiElement[] elementsToExtract) { - super(project); + super(project, true); myProject = project; myTargetClass = targetClass; myReturnType = returnType; diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java index c61c29c58ff9..e63b3751e425 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -463,14 +463,14 @@ public class ExtractMethodProcessor implements MatchProvider { protected void apply(final AbstractExtractDialog dialog) { myMethodName = dialog.getChosenMethodName(); myVariableDatum = dialog.getChosenParameters(); - myStatic |= dialog.isMakeStatic(); + myStatic = isStatic() | dialog.isMakeStatic(); myIsChainedConstructor = dialog.isChainedConstructor(); myMethodVisibility = dialog.getVisibility(); } protected AbstractExtractDialog createExtractMethodDialog(final boolean direct) { - return new ExtractMethodDialog(myProject, myTargetClass, myInputVariables, myReturnType, myTypeParameterList, - myThrownExceptions, myStatic, myCanBeStatic, myCanBeChainedConstructor, + return new ExtractMethodDialog(myProject, myTargetClass, myInputVariables, myReturnType, getTypeParameterList(), + getThrownExceptions(), isStatic(), isCanBeStatic(), myCanBeChainedConstructor, suggestInitialMethodName(), myRefactoringName, myHelpId, myElements) { protected boolean areTypesDirected() { @@ -620,7 +620,7 @@ public class ExtractMethodProcessor implements MatchProvider { private void doExtract() throws IncorrectOperationException { - PsiMethod newMethod = generateEmptyMethod(myThrownExceptions, myStatic); + PsiMethod newMethod = generateEmptyMethod(getThrownExceptions(), isStatic()); myExpression = myInputVariables.replaceWrappedReferences(myElements, myExpression); renameInputVariables(); @@ -991,6 +991,10 @@ public class ExtractMethodProcessor implements MatchProvider { return myTargetClass; } + public PsiType getReturnType() { + return myReturnType; + } + private PsiMethod generateEmptyMethod(PsiClassType[] exceptions, boolean isStatic) throws IncorrectOperationException { PsiMethod newMethod; if (myIsChainedConstructor) { @@ -1001,8 +1005,8 @@ public class ExtractMethodProcessor implements MatchProvider { PsiUtil.setModifierProperty(newMethod, PsiModifier.STATIC, isStatic); } PsiUtil.setModifierProperty(newMethod, myMethodVisibility, true); - if (myTypeParameterList != null) { - newMethod.getTypeParameterList().replace(myTypeParameterList); + if (getTypeParameterList() != null) { + newMethod.getTypeParameterList().replace(getTypeParameterList()); } PsiCodeBlock body = newMethod.getBody(); LOG.assertTrue(body != null); @@ -1400,4 +1404,28 @@ public class ExtractMethodProcessor implements MatchProvider { public InputVariables getInputVariables() { return myInputVariables; } + + public PsiTypeParameterList getTypeParameterList() { + return myTypeParameterList; + } + + public PsiClassType[] getThrownExceptions() { + return myThrownExceptions; + } + + public boolean isStatic() { + return myStatic; + } + + public boolean isCanBeStatic() { + return myCanBeStatic; + } + + public PsiElement[] getElements() { + return myElements; + } + + public PsiVariable[] getOutputVariables() { + return myOutputVariables; + } } diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java new file mode 100644 index 000000000000..c5ee560434a5 --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java @@ -0,0 +1,144 @@ +/* + * 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.refactoring.extractMethodObject; + +import com.intellij.codeInsight.CodeInsightUtil; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.refactoring.extractMethod.AbstractExtractDialog; +import com.intellij.refactoring.extractMethod.InputVariables; +import com.intellij.refactoring.util.VariableData; +import org.jetbrains.annotations.Nullable; + +public class ExtractLightMethodObjectHandler { + private static final Logger LOG = Logger.getInstance("#" + ExtractLightMethodObjectHandler.class.getName()); + + public static class ExtractedData { + private String myGeneratedCallText; + private PsiClass myGeneratedInnerClass; + + public ExtractedData(String generatedCallText, PsiClass generatedInnerClass) { + myGeneratedCallText = generatedCallText; + myGeneratedInnerClass = generatedInnerClass; + } + + public String getGeneratedCallText() { + return myGeneratedCallText; + } + + public PsiClass getGeneratedInnerClass() { + return myGeneratedInnerClass; + } + } + + @Nullable + public static ExtractedData extractLightMethodObject(final Project project, + final Editor editor, + final PsiFile file, + final PsiElement[] elements, + final String methodName) { + if (elements == null || elements.length == 0) { + return null; + } + + final PsiFile copy = PsiFileFactory.getInstance(project) + .createFileFromText(file.getName(), file.getFileType(), file.getText(), file.getModificationStamp(), true); + + final PsiElement[] elementsCopy = new PsiElement[elements.length]; + for (int i = 0; i < elements.length; i++) { + PsiElement element = elements[i]; + final TextRange textRange = element.getTextRange(); + elementsCopy[i] = CodeInsightUtil.findElementInRange(copy, textRange.getStartOffset(), textRange.getEndOffset(), element.getClass()); + } + + final Document document = PsiDocumentManager.getInstance(project).getDocument(copy); + LOG.assertTrue(document != null); + + final int startOffset = elements[0].getTextRange().getStartOffset(); + final int endOffset = elements[elements.length - 1].getTextRange().getEndOffset(); + + final RangeMarker callSiteMarker = document.createRangeMarker(startOffset, endOffset); + callSiteMarker.setGreedyToLeft(true); + callSiteMarker.setGreedyToRight(true); + + try { + final ExtractMethodObjectProcessor extractMethodObjectProcessor = new ExtractMethodObjectProcessor(project, editor, elementsCopy, "") { + @Override + protected AbstractExtractDialog createExtractMethodObjectDialog(MyExtractMethodProcessor processor) { + return new LightExtractMethodObjectDialog(this, methodName); + } + }; + extractMethodObjectProcessor.getExtractProcessor().setShowErrorDialogs(false); + + ExtractMethodObjectHandler.extractMethodObject(project, editor, file, extractMethodObjectProcessor); + + final String generatedCall = document.getText(new TextRange(callSiteMarker.getStartOffset(), callSiteMarker.getEndOffset())); + return new ExtractedData(generatedCall, extractMethodObjectProcessor.getInnerClass()); + } + finally { + callSiteMarker.dispose(); + } + } + + private static class LightExtractMethodObjectDialog implements AbstractExtractDialog { + private final ExtractMethodObjectProcessor myProcessor; + private final String myMethodName; + + public LightExtractMethodObjectDialog(ExtractMethodObjectProcessor processor, String methodName) { + myProcessor = processor; + myMethodName = methodName; + } + + @Override + public String getChosenMethodName() { + return myMethodName; + } + + @Override + public VariableData[] getChosenParameters() { + final InputVariables inputVariables = myProcessor.getExtractProcessor().getInputVariables(); + return inputVariables.getInputVariables().toArray(new VariableData[inputVariables.getInputVariables().size()]); + } + + @Override + public String getVisibility() { + return PsiModifier.PUBLIC; + } + + @Override + public boolean isMakeStatic() { + return false; + } + + @Override + public boolean isChainedConstructor() { + return false; + } + + @Override + public void show() {} + + @Override + public boolean isOK() { + return true; + } + } +} diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java index fddd19bb4630..f79280fd1365 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java @@ -19,6 +19,7 @@ import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.*; @@ -44,7 +45,7 @@ import java.awt.event.ActionListener; import java.util.Enumeration; -public class ExtractMethodObjectDialog extends AbstractExtractDialog { +public class ExtractMethodObjectDialog extends DialogWrapper implements AbstractExtractDialog { private final Project myProject; private final PsiType myReturnType; private final PsiTypeParameterList myTypeParameterList; @@ -86,7 +87,7 @@ public class ExtractMethodObjectDialog extends AbstractExtractDialog { public ExtractMethodObjectDialog(Project project, PsiClass targetClass, final InputVariables inputVariables, PsiType returnType, PsiTypeParameterList typeParameterList, PsiType[] exceptions, boolean isStatic, boolean canBeStatic, final PsiElement[] elementsToExtract, final boolean multipleExitPoints) { - super(project); + super(project, true); myProject = project; myTargetClass = targetClass; myReturnType = returnType; diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectHandler.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectHandler.java index d8fb3fd6ef87..b09a02cfd561 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectHandler.java @@ -20,26 +20,29 @@ */ package com.intellij.refactoring.extractMethodObject; +import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pass; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; +import com.intellij.psi.*; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringBundle; +import com.intellij.refactoring.extractMethod.AbstractExtractDialog; import com.intellij.refactoring.extractMethod.ExtractMethodHandler; +import com.intellij.refactoring.extractMethod.InputVariables; import com.intellij.refactoring.extractMethod.PrepareFailedException; import com.intellij.refactoring.util.CommonRefactoringUtil; +import com.intellij.refactoring.util.VariableData; import com.intellij.refactoring.util.duplicates.DuplicatesImpl; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -55,7 +58,10 @@ public class ExtractMethodObjectHandler implements RefactoringActionHandler { }); } - private void invokeOnElements(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file, @NotNull PsiElement[] elements) { + private static void invokeOnElements(@NotNull final Project project, + @NotNull final Editor editor, + @NotNull PsiFile file, + @NotNull PsiElement[] elements) { if (elements.length == 0) { String message = RefactoringBundle .getCannotRefactorMessage(RefactoringBundle.message("selected.block.should.represent.a.set.of.statements.or.an.expression")); @@ -63,7 +69,10 @@ public class ExtractMethodObjectHandler implements RefactoringActionHandler { return; } - final ExtractMethodObjectProcessor processor = new ExtractMethodObjectProcessor(project, editor, elements, ""); + extractMethodObject(project, editor, file, new ExtractMethodObjectProcessor(project, editor, elements, "")); + } + + static void extractMethodObject(Project project, Editor editor, PsiFile file, ExtractMethodObjectProcessor processor) { final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor = processor.getExtractProcessor(); try { if (!extractProcessor.prepare()) return; diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java index 7f95c49c65b3..20c536bb5a1d 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectProcessor.java @@ -37,10 +37,13 @@ import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.controlFlow.ControlFlowUtil; import com.intellij.psi.impl.source.PsiImmediateClassType; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor; @@ -52,6 +55,7 @@ import com.intellij.refactoring.ui.MemberSelectionPanel; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.refactoring.util.classMembers.MemberInfo; import com.intellij.refactoring.util.duplicates.Match; +import com.intellij.testFramework.LightVirtualFile; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.intellij.usageView.UsageViewUtil; @@ -100,8 +104,12 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { @NotNull protected UsageInfo[] findUsages() { final ArrayList result = new ArrayList(); + final PsiClass containingClass = getMethod().getContainingClass(); + final SearchScope scope = PsiUtilCore.getVirtualFile(containingClass) instanceof LightVirtualFile + ? new LocalSearchScope(containingClass) + : GlobalSearchScope.projectScope(myProject); PsiReference[] refs = - ReferencesSearch.search(getMethod(), GlobalSearchScope.projectScope(myProject), false).toArray(PsiReference.EMPTY_ARRAY); + ReferencesSearch.search(getMethod(), scope, false).toArray(PsiReference.EMPTY_ARRAY); for (PsiReference ref : refs) { final PsiElement element = ref.getElement(); if (element != null && element.isValid()) { @@ -320,7 +328,7 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { for (PsiElement declaredElement : declaredElements) { if (declaredElement instanceof PsiVariable) { for (PsiVariable variable : outputVariables) { - PsiLocalVariable var = (PsiLocalVariable)declaredElement; + PsiVariable var = (PsiVariable)declaredElement; if (Comparing.strEqual(var.getName(), variable.getName())) { final PsiExpression initializer = var.getInitializer(); if (initializer == null) { @@ -400,8 +408,7 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { private String getPureName(PsiVariable var) { final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(myProject); - final VariableKind kind = var instanceof PsiLocalVariable ? VariableKind.LOCAL_VARIABLE : VariableKind.PARAMETER; - return styleManager.variableNameToPropertyName(var.getName(), kind); + return styleManager.variableNameToPropertyName(var.getName(), styleManager.getVariableKind(var)); } public PsiExpression processMethodDeclaration( PsiExpressionList expressionList) throws IncorrectOperationException { @@ -517,7 +524,7 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { LOG.assertTrue(methodBody != null); replacedMethodBody.replace(methodBody); PsiUtil.setModifierProperty(newMethod, PsiModifier.STATIC, myInnerClass.hasModifierProperty(PsiModifier.STATIC) && notHasGeneratedFields()); - myInnerMethod = (PsiMethod)myInnerClass.add(newMethod); + myInnerMethod = (PsiMethod)JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(myInnerClass.add(newMethod)); } private boolean notHasGeneratedFields() { @@ -624,6 +631,22 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { return myExtractProcessor; } + protected AbstractExtractDialog createExtractMethodObjectDialog(final MyExtractMethodProcessor processor) { + return new ExtractMethodObjectDialog(myProject, processor.getTargetClass(), processor.getInputVariables(), processor.getReturnType(), + processor.getTypeParameterList(), + processor.getThrownExceptions(), processor.isStatic(), processor.isCanBeStatic(), + processor.getElements(), myMultipleExitPoints){ + @Override + protected boolean isUsedAfter(PsiVariable variable) { + return ArrayUtil.find(processor.getOutputVariables(), variable) != -1; + } + }; + } + + public PsiClass getInnerClass() { + return myInnerClass; + } + public class MyExtractMethodProcessor extends ExtractMethodProcessor { public MyExtractMethodProcessor(Project project, @@ -640,19 +663,13 @@ public class ExtractMethodObjectProcessor extends BaseRefactoringProcessor { @Override protected void apply(final AbstractExtractDialog dialog) { super.apply(dialog); - myCreateInnerClass = ((ExtractMethodObjectDialog)dialog).createInnerClass(); + myCreateInnerClass = !(dialog instanceof ExtractMethodObjectDialog) || ((ExtractMethodObjectDialog)dialog).createInnerClass(); myInnerClassName = myCreateInnerClass ? StringUtil.capitalize(dialog.getChosenMethodName()) : dialog.getChosenMethodName(); } @Override protected AbstractExtractDialog createExtractMethodDialog(final boolean direct) { - return new ExtractMethodObjectDialog(myProject, myTargetClass, myInputVariables, myReturnType, myTypeParameterList, - myThrownExceptions, myStatic, myCanBeStatic, myElements, myMultipleExitPoints){ - @Override - protected boolean isUsedAfter(PsiVariable variable) { - return ArrayUtil.find(myOutputVariables, variable) != -1; - } - }; + return createExtractMethodObjectDialog(this); } @Override diff --git a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java index c835a4171f74..163055f442fa 100644 --- a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java @@ -262,7 +262,9 @@ public class GenericsUtil { for (PsiTypeParameter typeParameter : typeParams) { PsiType substituted = substitutor.substitute(typeParameter); if (substituted == null) return null; - substituted = PsiUtil.captureToplevelWildcards(substituted, context); + if (context != null) { + substituted = PsiUtil.captureToplevelWildcards(substituted, context); + } PsiClassType[] extendsTypes = typeParameter.getExtendsListTypes(); for (PsiClassType type : extendsTypes) { @@ -349,6 +351,9 @@ public class GenericsUtil { @Nullable public static PsiType getVariableTypeByExpressionType(@Nullable PsiType type, final boolean openCaptured) { if (type == null) return null; + if (type instanceof PsiDisjunctionType) { + type = ((PsiDisjunctionType)type).getLeastUpperBound(); + } if (type instanceof PsiCapturedWildcardType) { type = ((PsiCapturedWildcardType)type).getWildcard(); } diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index 198bad10c1db..8ff42ca085a0 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -484,7 +484,8 @@ public class LambdaUtil { (((PsiPrefixExpression)body).getOperationTokenType() == JavaTokenType.PLUSPLUS || ((PsiPrefixExpression)body).getOperationTokenType() == JavaTokenType.MINUSMINUS) || body instanceof PsiPostfixExpression || - body instanceof PsiCallExpression; + body instanceof PsiCallExpression || + body instanceof PsiReferenceExpression && !body.isPhysical(); } public static class TypeParamsChecker extends PsiTypeVisitor { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java index 9c9525aef859..d53bb2e26820 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java @@ -389,7 +389,7 @@ public class PsiSubstitutorImpl implements PsiSubstitutor { } else { //unbounded - substituted = PsiWildcardType.createExtends(manager, substitutedBoundType); + substituted = substitutedBoundType instanceof PsiCapturedWildcardType ? ((PsiCapturedWildcardType)substitutedBoundType).getWildcard() : PsiWildcardType.createExtends(manager, substitutedBoundType); } } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index e3c6d2341dc8..d93b7565c988 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -1205,9 +1205,6 @@ public class InferenceSession { } final List returnExpressions = LambdaUtil.getReturnExpressions((PsiLambdaExpression)arg); - if (sReturnType == PsiType.VOID) { - return returnExpressions.isEmpty() && session == null; - } if (LambdaUtil.isFunctionalType(sReturnType) && LambdaUtil.isFunctionalType(tReturnType) && !TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(sReturnType), TypeConversionUtil.erasure(tReturnType)) && @@ -1263,10 +1260,6 @@ public class InferenceSession { return true; } - if (sReturnType == PsiType.VOID && session != null) { - return false; - } - final boolean sPrimitive = sReturnType instanceof PsiPrimitiveType && sReturnType != PsiType.VOID; final boolean tPrimitive = tReturnType instanceof PsiPrimitiveType && tReturnType != PsiType.VOID; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CaptureWildcardFromUnboundCaptureWildcard.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CaptureWildcardFromUnboundCaptureWildcard.java new file mode 100644 index 000000000000..0abec87dc335 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/CaptureWildcardFromUnboundCaptureWildcard.java @@ -0,0 +1,9 @@ +class Test & Runnable> {} + +interface Supplier { + K get(); +} + +interface Getter extends Supplier { + public S get(); +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA106985.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA106985.java new file mode 100644 index 000000000000..b11bfa46632c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA106985.java @@ -0,0 +1,15 @@ + +import java.util.Map; + +class Test { + + public static void main(String[] args) { + Map map = make(); + } + + + public static Map make() { + return null; + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IncompatibleBoundsFromAssignment.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IncompatibleBoundsFromAssignment.java new file mode 100644 index 000000000000..d5b8b03050d5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IncompatibleBoundsFromAssignment.java @@ -0,0 +1,15 @@ +import java.util.Map; + +class Test { + + public static void main(String[] args) { + Map b = newMapTrie(); + Map> c = newMapTrie(); + Map>> d = newMapTrie(); + Map>>> e = newMapTrie(); + } + + public static > T newMapTrie() { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Ambiguity1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Ambiguity1.java index e66630146e6f..02bbebd074b0 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Ambiguity1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Ambiguity1.java @@ -12,7 +12,7 @@ class Ambiguity1 { static void m(I2 i2) {} { - m(()->{throw new AssertionError();}); + m(()->{throw new AssertionError();}); m(() -> {}); m(() -> { if (false) return; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityRawGenerics.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityRawGenerics.java index 595787704437..6c664dd9e65a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityRawGenerics.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityRawGenerics.java @@ -22,6 +22,6 @@ class AmbiguityRawGenerics { void foo(I3 s) { } void bar() { - foo(()-> { throw new RuntimeException(); }); + foo(()-> { throw new RuntimeException(); }); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/NoReturnTypeResolutionForThrownException.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/NoReturnTypeResolutionForThrownException.java index 81429131d099..1fe14f680abe 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/NoReturnTypeResolutionForThrownException.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/mostSpecific/NoReturnTypeResolutionForThrownException.java @@ -7,7 +7,7 @@ class Test { void call(I2 p) { } void test() { - call(() -> { throw new RuntimeException(); }); + call(() -> { throw new RuntimeException(); }); call(() -> { if (true) return ""; throw new RuntimeException(); }); call(() -> { if (true) return; throw new RuntimeException(); }); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeMethodSignatureFromUsage8/afterDisjunctionType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeMethodSignatureFromUsage8/afterDisjunctionType.java new file mode 100644 index 000000000000..7835cfb40ae9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeMethodSignatureFromUsage8/afterDisjunctionType.java @@ -0,0 +1,15 @@ +// "Add 'Exception' as 1st parameter to method 'f'" "true" +import java.io.FileInputStream; +import java.io.IOException; + +class Test { + public void createFileInputStream() { + try { + new FileInputStream("test"); + } catch (IOException |NullPointerException e) { + f(e); + } + } + + public void f(Exception e) { } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeMethodSignatureFromUsage8/beforeDisjunctionType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeMethodSignatureFromUsage8/beforeDisjunctionType.java new file mode 100644 index 000000000000..ab28d7484f4d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeMethodSignatureFromUsage8/beforeDisjunctionType.java @@ -0,0 +1,15 @@ +// "Add 'Exception' as 1st parameter to method 'f'" "true" +import java.io.FileInputStream; +import java.io.IOException; + +class Test { + public void createFileInputStream() { + try { + new FileInputStream("test"); + } catch (IOException |NullPointerException e) { + f(e); + } + } + + public void f() { } +} diff --git a/java/java-tests/testData/refactoring/extractMethodObject4Debugger/SimpleGeneration.java b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/SimpleGeneration.java new file mode 100644 index 000000000000..178a4844ef5f --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethodObject4Debugger/SimpleGeneration.java @@ -0,0 +1,7 @@ +class Sample { + void foo() { + int i = 0; + int j = 0; + System.out.println(i + j); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index 09225b64bc1d..0a93d8f7f193 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -372,6 +372,8 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA126633() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testIDEA124363() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testIDEA78402() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testIDEA106985() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testCaptureWildcardFromUnboundCaptureWildcard() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testSuperCaptureSubstitutionWhenTypeParameterHasUpperBounds() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } public void testParameterBoundsWithCapturedWildcard() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } //jdk should propagate LL 1.4 but actually it provides LL 1.7?! diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java index e6e4534b6560..9ec2d29b71e3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java @@ -236,6 +236,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase doTest(); } + public void testIncompatibleBoundsFromAssignment() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index 1b56554333b0..712df26e356f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -22,6 +22,8 @@ import com.intellij.idea.Bombed; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.testFramework.IdeaTestUtil; +import junit.framework.Test; +import junit.framework.TestSuite; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -107,7 +109,6 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } - @Bombed(day = 30, month = Calendar.SEPTEMBER) public void testIDEA124983() throws Exception { doTest(); } @@ -145,4 +146,12 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { protected Sdk getProjectJDK() { return IdeaTestUtil.getMockJdk18(); } +/* + public static Test suite() { + final TestSuite suite = new TestSuite(); + for (int i = 0; i < 100; i++) { + suite.addTestSuite(NewLambdaHighlightingTest.class); + } + return suite; + }*/ } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObject4DebuggerTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObject4DebuggerTest.java new file mode 100644 index 000000000000..64e355126e2f --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodObject4DebuggerTest.java @@ -0,0 +1,84 @@ +/* + * 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. + */ + +/* + * User: anna + * Date: 06-May-2008 + */ +package com.intellij.refactoring; + +import com.intellij.JavaTestUtil; +import com.intellij.codeInsight.CodeInsightUtil; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler; +import com.intellij.testFramework.IdeaTestUtil; +import org.jetbrains.annotations.NotNull; + +public class ExtractMethodObject4DebuggerTest extends LightRefactoringTestCase { + @NotNull + @Override + protected String getTestDataPath() { + return JavaTestUtil.getJavaTestDataPath(); + } + + private void doTest(String expectedCallSite, String expectedClass) throws Exception { + final String testName = getTestName(false); + configureByFile("/refactoring/extractMethodObject4Debugger/" + testName + ".java"); + int startOffset = getEditor().getSelectionModel().getSelectionStart(); + int endOffset = getEditor().getSelectionModel().getSelectionEnd(); + PsiElement[] elements = CodeInsightUtil.findStatementsInRange(getFile(), startOffset, endOffset); + assertTrue(elements.length > 0); + + final ExtractLightMethodObjectHandler.ExtractedData extractedData = + ExtractLightMethodObjectHandler.extractLightMethodObject(getProject(), getEditor(), getFile(), elements, "test"); + assertNotNull(extractedData); + assertEquals(expectedCallSite, extractedData.getGeneratedCallText()); + final PsiClass innerClass = extractedData.getGeneratedInnerClass(); + assertEquals(expectedClass, innerClass.getText()); + } + + public void testSimpleGeneration() throws Exception { + doTest(" Test test = new Test().invoke();\n" + + " int i = test.getI();\n" + + " int j = test.getJ();", + + "public class Test {\n" + + " private int i;\n" + + " private int j;\n" + + "\n" + + " public int getI() {\n" + + " return i;\n" + + " }\n" + + "\n" + + " public int getJ() {\n" + + " return j;\n" + + " }\n" + + "\n" + + " public Test invoke() {\n" + + " i = 0;\n" + + " j = 0;\n" + + " return this;\n" + + " }\n" + + " }"); + } + + @Override + protected Sdk getProjectJDK() { + return IdeaTestUtil.getMockJdk18(); + } +} diff --git a/java/openapi/src/com/intellij/execution/filters/ExceptionWorker.java b/java/openapi/src/com/intellij/execution/filters/ExceptionWorker.java index 680ae8f744ce..c912e57999dd 100644 --- a/java/openapi/src/com/intellij/execution/filters/ExceptionWorker.java +++ b/java/openapi/src/com/intellij/execution/filters/ExceptionWorker.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. @@ -48,18 +48,6 @@ public class ExceptionWorker { private static final String AT_PREFIX = AT + " "; private static final String STANDALONE_AT = " " + AT + " "; - private static final TextAttributes HYPERLINK_ATTRIBUTES; - private static final TextAttributes LIBRARY_HYPERLINK_ATTRIBUTES; - - static { - HYPERLINK_ATTRIBUTES = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.HYPERLINK_ATTRIBUTES); - - LIBRARY_HYPERLINK_ATTRIBUTES = HYPERLINK_ATTRIBUTES.clone(); - Color libTextColor = UIUtil.getInactiveTextColor(); - LIBRARY_HYPERLINK_ATTRIBUTES.setForegroundColor(libTextColor); - LIBRARY_HYPERLINK_ATTRIBUTES.setEffectColor(libTextColor); - } - private final Project myProject; private Filter.Result myResult; private PsiClass[] myClasses = PsiClass.EMPTY_ARRAY; @@ -129,13 +117,16 @@ public class ExceptionWorker { } List virtualFiles; - TextAttributes attributes; + TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(CodeInsightColors.HYPERLINK_ATTRIBUTES); if (virtualFilesInContent.isEmpty()) { - attributes = LIBRARY_HYPERLINK_ATTRIBUTES; + Color libTextColor = UIUtil.getInactiveTextColor(); + attributes = attributes.clone(); + attributes.setForegroundColor(libTextColor); + attributes.setEffectColor(libTextColor); + virtualFiles = virtualFilesInLibraries; } else { - attributes = HYPERLINK_ATTRIBUTES; virtualFiles = virtualFilesInContent; } HyperlinkInfo linkInfo = HyperlinkInfoFactory.getInstance().createMultipleFilesHyperlinkInfo(virtualFiles, lineNumber - 1, myProject); diff --git a/native/WinLauncher/WinLauncher/WinLauncher.cpp b/native/WinLauncher/WinLauncher/WinLauncher.cpp index 3249a9a1f0de..681cb46ae6aa 100644 --- a/native/WinLauncher/WinLauncher/WinLauncher.cpp +++ b/native/WinLauncher/WinLauncher/WinLauncher.cpp @@ -194,11 +194,16 @@ bool LocateJVM() return result; } - std::string jreDir = GetAdjacentDir(need64BitJRE ? "jre64":"jre"); - if (FindValidJVM(jreDir.c_str()) && Is64BitJRE(jvmPath) == need64BitJRE) - { - return true; - } + + std::vector jrePaths; + if(need64BitJRE) jrePaths.push_back(GetAdjacentDir("jre64")); + jrePaths.push_back(GetAdjacentDir("jre")); + for(std::vector::iterator it = jrePaths.begin(); it != jrePaths.end(); ++it) { + if (FindValidJVM((*it).c_str()) && Is64BitJRE(jvmPath) == need64BitJRE) + { + return true; + } + } if (FindJVMInRegistry()) { diff --git a/platform/core-api/src/com/intellij/concurrency/AsyncUtil.java b/platform/core-api/src/com/intellij/concurrency/AsyncUtil.java index 93c7573c0381..72c0a85aac72 100644 --- a/platform/core-api/src/com/intellij/concurrency/AsyncUtil.java +++ b/platform/core-api/src/com/intellij/concurrency/AsyncUtil.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,12 +18,17 @@ package com.intellij.concurrency; import org.jetbrains.annotations.NotNull; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executor; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; /** * Author: dmitrylomov */ public class AsyncUtil { + private static final AsyncFuture TRUE = createConst(true); + private static final AsyncFuture FALSE = createConst(false); + public static V get(@NotNull Future result) { try { return result.get(); @@ -41,4 +46,43 @@ public class AsyncUtil { } } } + + private static AsyncFuture createConst(final boolean result) { + return new AsyncFuture() { + @Override + public void addConsumer(@NotNull Executor executor, @NotNull ResultConsumer consumer) { + consumer.onSuccess(result); + } + + @Override + public boolean cancel(boolean mayInterruptIfRunning) { + return false; + } + + @Override + public boolean isCancelled() { + return false; + } + + @Override + public boolean isDone() { + return true; + } + + @Override + public Boolean get() { + return result; + } + + @Override + public Boolean get(long timeout, @NotNull TimeUnit unit) { + return result; + } + }; + } + + @NotNull + public static AsyncFuture wrapBoolean(boolean result) { + return result ? TRUE : FALSE; + } } diff --git a/platform/core-api/src/com/intellij/concurrency/DefaultResultConsumer.java b/platform/core-api/src/com/intellij/concurrency/DefaultResultConsumer.java index 7230cd469e13..0e54993fe84b 100644 --- a/platform/core-api/src/com/intellij/concurrency/DefaultResultConsumer.java +++ b/platform/core-api/src/com/intellij/concurrency/DefaultResultConsumer.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. @@ -15,13 +15,15 @@ */ package com.intellij.concurrency; +import org.jetbrains.annotations.NotNull; + /** * Author: dmitrylomov */ public class DefaultResultConsumer implements ResultConsumer { private final AsyncFutureResult myResult; - public DefaultResultConsumer(AsyncFutureResult result) { + public DefaultResultConsumer(@NotNull AsyncFutureResult result) { myResult = result; } @@ -31,7 +33,7 @@ public class DefaultResultConsumer implements ResultConsumer { } @Override - public void onFailure(Throwable t) { + public void onFailure(@NotNull Throwable t) { myResult.setException(t); } } diff --git a/platform/core-api/src/com/intellij/concurrency/DoWhile.java b/platform/core-api/src/com/intellij/concurrency/DoWhile.java deleted file mode 100644 index b77e3258c984..000000000000 --- a/platform/core-api/src/com/intellij/concurrency/DoWhile.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2000-2013 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.concurrency; - -import org.jetbrains.annotations.NotNull; - -/** - * Author: dmitrylomov - */ -public abstract class DoWhile { - private final AsyncFutureResult myResult = AsyncFutureFactory.getInstance().createAsyncFutureResult(); - private final SameThreadExecutorWithTrampoline myExecutor = new SameThreadExecutorWithTrampoline(); - - @NotNull - public AsyncFutureResult getResult() { - body().addConsumer(myExecutor, new MyConsumer()); - return myResult; - } - - @NotNull - protected abstract AsyncFuture body(); - protected abstract boolean condition(); - - private class MyConsumer extends DefaultResultConsumer { - public MyConsumer() { - super(DoWhile.this.myResult); - } - - @Override - public void onSuccess(Boolean value) { - if (!value.booleanValue()) { - myResult.set(false); - } - else { - if(!condition()) { - myResult.set(true); - } - else { - body().addConsumer(myExecutor, this); - } - } - } - } - - -} diff --git a/platform/core-api/src/com/intellij/concurrency/Iterate.java b/platform/core-api/src/com/intellij/concurrency/Iterate.java deleted file mode 100644 index e158999f4da5..000000000000 --- a/platform/core-api/src/com/intellij/concurrency/Iterate.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.intellij.concurrency; - -import org.jetbrains.annotations.NotNull; - -import java.util.Iterator; - -/** - * Author: dmitrylomov - */ -public abstract class Iterate extends DoWhile { - private final Iterator myIterator; - private boolean myIsDone; - - public Iterate(@NotNull Iterable iterable) { - myIterator = iterable.iterator(); - myIsDone = false; - } - - @NotNull - @Override - protected final AsyncFuture body() { - if (!myIterator.hasNext()) { - myIsDone = true; - return AsyncFutureFactory.wrap(true); - } - return process(myIterator.next()); - } - - @NotNull - protected abstract AsyncFuture process(T t); - - @Override - protected boolean condition() { - return !myIsDone; - } -} diff --git a/platform/core-api/src/com/intellij/concurrency/ResultConsumer.java b/platform/core-api/src/com/intellij/concurrency/ResultConsumer.java index 80618f0b9c79..409d5a9439a4 100644 --- a/platform/core-api/src/com/intellij/concurrency/ResultConsumer.java +++ b/platform/core-api/src/com/intellij/concurrency/ResultConsumer.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. @@ -15,10 +15,12 @@ */ package com.intellij.concurrency; +import org.jetbrains.annotations.NotNull; + /** * Author: dmitrylomov */ public interface ResultConsumer { void onSuccess(V value); - void onFailure(Throwable t); + void onFailure(@NotNull Throwable t); } diff --git a/platform/core-api/src/com/intellij/util/AbstractQuery.java b/platform/core-api/src/com/intellij/util/AbstractQuery.java index 1c29ef6437ac..219aae614140 100644 --- a/platform/core-api/src/com/intellij/util/AbstractQuery.java +++ b/platform/core-api/src/com/intellij/util/AbstractQuery.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. @@ -16,9 +16,7 @@ package com.intellij.util; import com.intellij.concurrency.AsyncFuture; -import com.intellij.concurrency.AsyncFutureFactory; -import com.intellij.concurrency.AsyncFutureResult; -import com.intellij.concurrency.FinallyFuture; +import com.intellij.concurrency.AsyncUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -84,26 +82,13 @@ public abstract class AbstractQuery implements Query { @NotNull @Override public AsyncFuture forEachAsync(@NotNull Processor consumer) { - assertNotProcessing(); - myIsProcessing = true; - return new FinallyFuture(processResultsAsync(consumer), new Runnable() { - @Override - public void run() { - myIsProcessing = false; - } - }); + return AsyncUtil.wrapBoolean(forEach(consumer)); } protected abstract boolean processResults(@NotNull Processor consumer); @NotNull protected AsyncFuture processResultsAsync(@NotNull Processor consumer) { - final AsyncFutureResult result = AsyncFutureFactory.getInstance().createAsyncFutureResult(); - try { - result.set(processResults(consumer)); - } catch (Throwable t) { - result.setException(t); - } - return result; + return AsyncUtil.wrapBoolean(processResults(consumer)); } } diff --git a/platform/core-api/src/com/intellij/util/ArrayQuery.java b/platform/core-api/src/com/intellij/util/ArrayQuery.java index abe2f1001fe0..1b7760146de6 100644 --- a/platform/core-api/src/com/intellij/util/ArrayQuery.java +++ b/platform/core-api/src/com/intellij/util/ArrayQuery.java @@ -17,8 +17,7 @@ package com.intellij.util; import com.intellij.concurrency.AsyncFuture; -import com.intellij.concurrency.AsyncFutureFactory; -import com.intellij.concurrency.AsyncFutureResult; +import com.intellij.concurrency.AsyncUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -55,13 +54,7 @@ public class ArrayQuery implements Query { @NotNull @Override public AsyncFuture forEachAsync(@NotNull final Processor consumer) { - final AsyncFutureResult result = AsyncFutureFactory.getInstance().createAsyncFutureResult(); - try { - result.set(forEach(consumer)); - } catch (Throwable t){ - result.setException(t); - } - return result; + return AsyncUtil.wrapBoolean(forEach(consumer)); } diff --git a/platform/core-api/src/com/intellij/util/CollectionQuery.java b/platform/core-api/src/com/intellij/util/CollectionQuery.java index cd90ab55edd9..253182cef0c1 100644 --- a/platform/core-api/src/com/intellij/util/CollectionQuery.java +++ b/platform/core-api/src/com/intellij/util/CollectionQuery.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. @@ -17,8 +17,7 @@ package com.intellij.util; import com.intellij.concurrency.AsyncFuture; -import com.intellij.concurrency.AsyncFutureFactory; -import com.intellij.concurrency.AsyncFutureResult; +import com.intellij.concurrency.AsyncUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -55,13 +54,7 @@ public class CollectionQuery implements Query { @NotNull @Override public AsyncFuture forEachAsync(@NotNull Processor consumer) { - AsyncFutureResult result = AsyncFutureFactory.getInstance().createAsyncFutureResult(); - try { - result.set(forEach(consumer)); - } catch (Throwable t) { - result.setException(t); - } - return result; + return AsyncUtil.wrapBoolean(forEach(consumer)); } @NotNull diff --git a/platform/core-api/src/com/intellij/util/EmptyQuery.java b/platform/core-api/src/com/intellij/util/EmptyQuery.java index 465100505450..18a32a5a94b4 100644 --- a/platform/core-api/src/com/intellij/util/EmptyQuery.java +++ b/platform/core-api/src/com/intellij/util/EmptyQuery.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. @@ -16,7 +16,7 @@ package com.intellij.util; import com.intellij.concurrency.AsyncFuture; -import com.intellij.concurrency.AsyncFutureFactory; +import com.intellij.concurrency.AsyncUtil; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -48,7 +48,7 @@ public class EmptyQuery implements Query { @NotNull @Override public AsyncFuture forEachAsync(@NotNull Processor consumer) { - return AsyncFutureFactory.wrap(true); + return AsyncUtil.wrapBoolean(true); } @NotNull diff --git a/platform/core-api/src/com/intellij/util/MergeQuery.java b/platform/core-api/src/com/intellij/util/MergeQuery.java index 699659b93055..35d122639cd3 100644 --- a/platform/core-api/src/com/intellij/util/MergeQuery.java +++ b/platform/core-api/src/com/intellij/util/MergeQuery.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. @@ -66,13 +66,13 @@ public class MergeQuery implements Query{ fq.addConsumer(SameThreadExecutor.INSTANCE, new DefaultResultConsumer(result) { @Override public void onSuccess(Boolean value) { - if (!value.booleanValue()) { - result.set(false); - } - else { + if (value.booleanValue()) { final AsyncFuture fq2 = processSubQueryAsync(consumer, myQuery2); fq2.addConsumer(SameThreadExecutor.INSTANCE, new DefaultResultConsumer(result)); } + else { + result.set(false); + } } }); return result; @@ -85,12 +85,7 @@ public class MergeQuery implements Query{ } private AsyncFuture processSubQueryAsync(@NotNull final Processor consumer, @NotNull Query query1) { - return query1.forEachAsync(new Processor() { - @Override - public boolean process(final V t) { - return consumer.process(t); - } - }); + return query1.forEachAsync((Processor)consumer); } @NotNull diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java index f82e7a80d5fb..cbb35b4f9812 100644 --- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java +++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java @@ -36,10 +36,7 @@ import com.intellij.openapi.extensions.ExtensionsArea; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.*; import com.intellij.openapi.progress.*; -import com.intellij.openapi.util.ClassExtension; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.KeyedExtensionCollector; -import com.intellij.openapi.util.StaticGetter; +import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileSystem; import com.intellij.openapi.vfs.encoding.EncodingRegistry; @@ -175,15 +172,7 @@ public class CoreApplicationEnvironment { ProgressIndicator progress, boolean failFastOnAcquireReadAction, @NotNull Processor thingProcessor) { - final AsyncFutureResult asyncFutureResult = AsyncFutureFactory.getInstance().createAsyncFutureResult(); - try { - final boolean result = invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor); - asyncFutureResult.set(result); - } - catch (Throwable t) { - asyncFutureResult.setException(t); - } - return asyncFutureResult; + return AsyncUtil.wrapBoolean(invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor)); } @NotNull diff --git a/platform/dvcs-api/src/com/intellij/dvcs/repo/Repository.java b/platform/dvcs-api/src/com/intellij/dvcs/repo/Repository.java index 47cc17866c08..c269d7ba993e 100644 --- a/platform/dvcs-api/src/com/intellij/dvcs/repo/Repository.java +++ b/platform/dvcs-api/src/com/intellij/dvcs/repo/Repository.java @@ -54,6 +54,8 @@ import org.jetbrains.annotations.Nullable; public interface Repository extends Disposable { + + /** * Current state of the repository. */ @@ -83,9 +85,8 @@ public interface Repository extends Disposable { /** * Detached HEAD state, but not during rebase (for example, manual checkout of a commit hash). */ - DETACHED + DETACHED; } - @NotNull VirtualFile getRoot(); @@ -98,6 +99,9 @@ public interface Repository extends Disposable { @NotNull State getState(); + @Nullable + String getCurrentBranchName(); + @Nullable AbstractVcs getVcs(); diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchPopup.java b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchPopup.java new file mode 100644 index 000000000000..a98cf27ab5d6 --- /dev/null +++ b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchPopup.java @@ -0,0 +1,174 @@ +/* + * 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.dvcs.branch; + +import com.intellij.dvcs.DvcsUtil; +import com.intellij.dvcs.repo.AbstractRepositoryManager; +import com.intellij.dvcs.repo.Repository; +import com.intellij.dvcs.ui.BranchActionGroupPopup; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationListener; +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.options.ShowSettingsUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.ListPopup; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vcs.AbstractVcs; +import com.intellij.openapi.vcs.VcsNotifier; +import com.intellij.ui.popup.list.ListPopupImpl; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.event.HyperlinkEvent; +import java.util.List; + +public abstract class DvcsBranchPopup { + @NotNull protected final Project myProject; + @NotNull protected final AbstractRepositoryManager myRepositoryManager; + @NotNull protected final DvcsSyncBranchSettings myVcsSettings; + @NotNull protected final AbstractVcs myVcs; + @NotNull protected final DvcsMultiRootBranchConfig myMultiRootBranchConfig; + + @NotNull protected final Repo myCurrentRepository; + @NotNull protected final ListPopupImpl myPopup; + + protected DvcsBranchPopup(@NotNull Repo currentRepository, + @NotNull AbstractRepositoryManager repositoryManager, + @NotNull DvcsMultiRootBranchConfig multiRootBranchConfig, + @NotNull DvcsSyncBranchSettings vcsSettings, + @NotNull Condition preselectActionCondition) { + myProject = currentRepository.getProject(); + myCurrentRepository = currentRepository; + myRepositoryManager = repositoryManager; + myVcs = currentRepository.getVcs(); + myVcsSettings = vcsSettings; + myMultiRootBranchConfig = multiRootBranchConfig; + String title = createPopupTitle(currentRepository); + myPopup = new BranchActionGroupPopup(title, myProject, preselectActionCondition, createActions()); + + initBranchSyncPolicyIfNotInitialized(); + setCurrentBranchInfo(); + warnThatBranchesDivergedIfNeeded(); + } + + public ListPopup asListPopup() { + return myPopup; + } + + private void initBranchSyncPolicyIfNotInitialized() { + if (myRepositoryManager.moreThanOneRoot() && myVcsSettings.getSyncSetting() == DvcsBranchSync.NOT_DECIDED) { + if (!myMultiRootBranchConfig.diverged()) { + notifyAboutSyncedBranches(); + myVcsSettings.setSyncSetting(DvcsBranchSync.SYNC); + } + else { + myVcsSettings.setSyncSetting(DvcsBranchSync.DONT); + } + } + } + + @NotNull + private String createPopupTitle(@NotNull Repo currentRepository) { + String title = myVcs.getDisplayName() + " Branches"; + if (myRepositoryManager.moreThanOneRoot() && + (myMultiRootBranchConfig.diverged() || myVcsSettings.getSyncSetting() == DvcsBranchSync.DONT)) { + title += " in " + DvcsUtil.getShortRepositoryName(currentRepository); + } + return title; + } + + protected void setCurrentBranchInfo() { + String branchText = "Current branch : "; + myPopup.setAdText(branchText + myCurrentRepository.getCurrentBranchName(), SwingConstants.CENTER); + } + + private void notifyAboutSyncedBranches() { + String description = + "You have several " + myVcs.getDisplayName() + "roots in the project and they all are checked out at the same branch. " + + "We've enabled synchronous branch control for the project.
" + + "If you wish to control branches in different roots separately, " + + "you may disable the setting."; + NotificationListener listener = new NotificationListener() { + @Override + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + ShowSettingsUtil.getInstance().showSettingsDialog(myProject, myVcs.getConfigurable().getDisplayName()); + if (myVcsSettings.getSyncSetting() == DvcsBranchSync.DONT) { + notification.expire(); + } + } + } + }; + VcsNotifier.getInstance(myProject).notifyImportantInfo("Synchronous branch control enabled", description, listener); + } + + @NotNull + private ActionGroup createActions() { + DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); + AbstractRepositoryManager repositoryManager = myRepositoryManager; + if (repositoryManager.moreThanOneRoot()) { + if (userWantsSyncControl()) { + fillWithCommonRepositoryActions(popupGroup, repositoryManager); + } + else { + fillPopupWithCurrentRepositoryActions(popupGroup, createRepositoriesActions()); + } + } + else { + fillPopupWithCurrentRepositoryActions(popupGroup, null); + } + popupGroup.addSeparator(); + return popupGroup; + } + + private boolean userWantsSyncControl() { + return (myVcsSettings.getSyncSetting() != DvcsBranchSync.DONT); + } + + protected abstract void fillWithCommonRepositoryActions(@NotNull DefaultActionGroup popupGroup, + @NotNull AbstractRepositoryManager repositoryManager); + + @NotNull + protected List filterRepositoriesNotOnThisBranch(@NotNull final String branch, + @NotNull List allRepositories) { + return ContainerUtil.filter(allRepositories, new Condition() { + @Override + public boolean value(Repo repository) { + return !branch.equals(repository.getCurrentBranchName()); + } + }); + } + + private void warnThatBranchesDivergedIfNeeded() { + if (myRepositoryManager.moreThanOneRoot() && myMultiRootBranchConfig.diverged() && userWantsSyncControl()) { + myPopup.setWarning("Branches have diverged"); + } + } + + @NotNull + protected abstract DefaultActionGroup createRepositoriesActions(); + + protected boolean highlightCurrentRepo() { + return !userWantsSyncControl() || myMultiRootBranchConfig.diverged(); + } + + protected abstract void fillPopupWithCurrentRepositoryActions(@NotNull DefaultActionGroup popupGroup, + @Nullable DefaultActionGroup actions); +} diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchSyncSetting.java b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchSync.java similarity index 80% rename from plugins/git4idea/src/git4idea/ui/branch/GitBranchSyncSetting.java rename to platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchSync.java index bb9c7592f028..9fab273be2e1 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchSyncSetting.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsBranchSync.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. @@ -13,12 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package git4idea.ui.branch; +package com.intellij.dvcs.branch; -/** - * @author Kirill Likhodedov - */ -public enum GitBranchSyncSetting { +public enum DvcsBranchSync { SYNC, DONT, NOT_DECIDED diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsMultiRootBranchConfig.java b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsMultiRootBranchConfig.java new file mode 100644 index 000000000000..ee24209167fa --- /dev/null +++ b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsMultiRootBranchConfig.java @@ -0,0 +1,71 @@ +/* + * 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.dvcs.branch; + +import com.intellij.dvcs.repo.Repository; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public abstract class DvcsMultiRootBranchConfig { + @NotNull protected final Collection myRepositories; + + public DvcsMultiRootBranchConfig(@NotNull Collection repositories) { + myRepositories = repositories; + } + + public boolean diverged() { + return getCurrentBranch() == null; + } + + @Nullable + public String getCurrentBranch() { + String commonBranch = null; + for (Repo repository : myRepositories) { + String branchName = repository.getCurrentBranchName(); + if (branchName == null) { + return null; + } + // NB: if all repositories are in the rebasing state on the same branches, this branch is returned + if (commonBranch == null) { + commonBranch = branchName; + } + else if (!commonBranch.equals(branchName)) { + return null; + } + } + return commonBranch; + } + + @Nullable + public Repository.State getState() { + Repository.State commonState = null; + for (Repo repository : myRepositories) { + Repository.State state = repository.getState(); + if (commonState == null) { + commonState = state; + } + else if (!commonState.equals(state)) { + return null; + } + } + return commonState; + } + + @NotNull + public abstract Collection getLocalBranchNames(); +} diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/RoamingTypeExtensionPointBean.java b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsSyncBranchSettings.java similarity index 58% rename from platform/platform-impl/src/com/intellij/openapi/components/impl/stores/RoamingTypeExtensionPointBean.java rename to platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsSyncBranchSettings.java index ff5d16361228..115872a66552 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/RoamingTypeExtensionPointBean.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/branch/DvcsSyncBranchSettings.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. @@ -13,17 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.openapi.components.impl.stores; +package com.intellij.dvcs.branch; -import com.intellij.util.xmlb.annotations.Attribute; +import org.jetbrains.annotations.NotNull; -/** - * @deprecated use {@link com.intellij.openapi.components.RoamingType#DISABLED} - */ -@Deprecated -public class RoamingTypeExtensionPointBean { - @Attribute("component") - public String componentName; - @Attribute("type") - public String roamingType; +public interface DvcsSyncBranchSettings { + @NotNull + DvcsBranchSync getSyncSetting(); + + void setSyncSetting(@NotNull DvcsBranchSync syncSetting); } diff --git a/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java b/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java index bef3d0350563..8f2db591888d 100644 --- a/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.java +++ b/platform/indexing-api/src/com/intellij/psi/search/PsiSearchHelper.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. @@ -58,7 +58,6 @@ public interface PsiSearchHelper { * * @param identifier the identifier to search. * @param searchScope the scope in which occurrences are searched. - * @param processor * @return false if processor returned false, true otherwise */ boolean processCommentsContainingIdentifier(@NotNull String identifier, @NotNull SearchScope searchScope, @NotNull Processor processor); diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index b5c3dd17afb7..ba8d9ce3500e 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -23,7 +23,6 @@ import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressIndicatorProvider; -import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.util.TooManyUsagesStatus; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.FileIndexFacade; @@ -56,7 +55,6 @@ import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.*; -import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -132,9 +130,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { short searchContext, boolean caseSensitive, boolean processInjectedPsi) { - final AsyncFuture result = - processElementsWithWordAsync(processor, searchScope, text, searchContext, caseSensitive, processInjectedPsi, null); - return AsyncUtil.get(result); + return processElementsWithWord(processor, searchScope, text, searchContext, caseSensitive, processInjectedPsi, null); } @NotNull @@ -144,50 +140,39 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { @NotNull final String text, final short searchContext, final boolean caseSensitively) { - return processElementsWithWordAsync(processor, searchScope, text, searchContext, caseSensitively, shouldProcessInjectedPsi(searchScope), null); + boolean result = + processElementsWithWord(processor, searchScope, text, searchContext, caseSensitively, shouldProcessInjectedPsi(searchScope), null); + return AsyncUtil.wrapBoolean(result); } - @NotNull - private AsyncFuture processElementsWithWordAsync(@NotNull final TextOccurenceProcessor processor, - @NotNull SearchScope searchScope, - @NotNull final String text, - final short searchContext, - final boolean caseSensitively, - boolean processInjectedPsi, - @Nullable String containerName) { + private boolean processElementsWithWord(@NotNull final TextOccurenceProcessor processor, + @NotNull SearchScope searchScope, + @NotNull final String text, + final short searchContext, + final boolean caseSensitively, + boolean processInjectedPsi, + @Nullable String containerName) { if (text.isEmpty()) { - return AsyncFutureFactory.wrapException(new IllegalArgumentException("Cannot search for elements with empty text")); + throw new IllegalArgumentException("Cannot search for elements with empty text"); } final ProgressIndicator progress = ProgressIndicatorProvider.getGlobalProgressIndicator(); if (searchScope instanceof GlobalSearchScope) { StringSearcher searcher = new StringSearcher(text, caseSensitively, true, searchContext == UsageSearchContext.IN_STRINGS); - return processElementsWithTextInGlobalScopeAsync(processor, - (GlobalSearchScope)searchScope, - searcher, - searchContext, caseSensitively, containerName, progress, processInjectedPsi); + return processElementsWithTextInGlobalScope(processor, + (GlobalSearchScope)searchScope, + searcher, + searchContext, caseSensitively, containerName, progress, processInjectedPsi); } LocalSearchScope scope = (LocalSearchScope)searchScope; PsiElement[] scopeElements = scope.getScope(); final StringSearcher searcher = new StringSearcher(text, caseSensitively, true, searchContext == UsageSearchContext.IN_STRINGS); Processor localProcessor = localProcessor(processor, progress, processInjectedPsi, searcher); - return wrapInFuture(Arrays.asList(scopeElements), progress, localProcessor); - } - - private static AsyncFuture wrapInFuture(@NotNull List files, final ProgressIndicator progress, @NotNull Processor processor) { - AsyncFutureResult asyncFutureResult = AsyncFutureFactory.getInstance().createAsyncFutureResult(); - try { - boolean result = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(files, progress, true, true, processor); - asyncFutureResult.set(result); - } - catch (Throwable t) { - asyncFutureResult.setException(t); - } - return asyncFutureResult; + return JobLauncher.getInstance().invokeConcurrentlyUnderProgress(Arrays.asList(scopeElements), progress, true, true, localProcessor); } private static boolean shouldProcessInjectedPsi(SearchScope scope) { - return scope instanceof LocalSearchScope ? !((LocalSearchScope)scope).isIgnoreInjectedPsi() : true; + return !(scope instanceof LocalSearchScope) || !((LocalSearchScope)scope).isIgnoreInjectedPsi(); } @NotNull @@ -213,14 +198,13 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { }; } - @NotNull - private AsyncFuture processElementsWithTextInGlobalScopeAsync(@NotNull final TextOccurenceProcessor processor, - @NotNull final GlobalSearchScope scope, - @NotNull final StringSearcher searcher, - final short searchContext, - final boolean caseSensitively, - String containerName, - final ProgressIndicator progress, final boolean processInjectedPsi) { + private boolean processElementsWithTextInGlobalScope(@NotNull final TextOccurenceProcessor processor, + @NotNull final GlobalSearchScope scope, + @NotNull final StringSearcher searcher, + final short searchContext, + final boolean caseSensitively, + String containerName, + final ProgressIndicator progress, final boolean processInjectedPsi) { if (Thread.holdsLock(PsiLock.LOCK)) { throw new AssertionError("You must not run search from within updating PSI activity. Please consider invokeLatering it instead."); } @@ -244,70 +228,28 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { getFilesWithText(scope, searchContext, caseSensitively, text+" "+containerName, progress, intersectionWithContainerFiles); if (!intersectionWithContainerFiles.isEmpty()) { int totalSize = fileSet.size(); - AsyncFuture intersectionResult = processPsiFileRootsAsync(intersectionWithContainerFiles, totalSize, 0, progress, localProcessor); - AsyncFuture result; - try { - if (intersectionResult.get()) { - fileSet.removeAll(intersectionWithContainerFiles); - if (fileSet.isEmpty()) { - result = intersectionResult; - } - else { - AsyncFuture restResult = - processPsiFileRootsAsync(new ArrayList(fileSet), totalSize, intersectionWithContainerFiles.size(), progress, localProcessor); - result = bind(intersectionResult, restResult); - } - } - else { - result = intersectionResult; + boolean result = processPsiFileRoots(intersectionWithContainerFiles, totalSize, 0, progress, + localProcessor); + + if (result) { + fileSet.removeAll(intersectionWithContainerFiles); + if (!fileSet.isEmpty()) { + result = processPsiFileRoots(new ArrayList(fileSet), totalSize, intersectionWithContainerFiles.size(), progress, localProcessor); } } - catch (ExecutionException e) { - Throwable cause = e.getCause(); - if (cause instanceof RuntimeException) throw (RuntimeException)cause; - if (cause instanceof Error) throw (Error)cause; - result = AsyncFutureFactory.wrapException(cause); - } - catch (InterruptedException e) { - result = AsyncFutureFactory.wrapException(e); - } - return popStateAfter(result, progress); - } - } - - AsyncFuture result = fileSet.isEmpty() - ? AsyncFutureFactory.wrap(Boolean.TRUE) - : processPsiFileRootsAsync(new ArrayList(fileSet), fileSet.size(), 0, progress, localProcessor); - return popStateAfter(result, progress); - } - - @NotNull - private static FinallyFuture popStateAfter(@NotNull AsyncFuture result, final ProgressIndicator progress) { - return new FinallyFuture(result, new Runnable() { - @Override - public void run() { if (progress != null) { progress.popState(); } + return result; } - }); - } + } - @NotNull - private static AsyncFuture bind(@NotNull AsyncFuture first, @NotNull final AsyncFuture second) { - final AsyncFutureResult totalResult = AsyncFutureFactory.getInstance().createAsyncFutureResult(); - first.addConsumer(SameThreadExecutor.INSTANCE, new ResultConsumer() { - @Override - public void onSuccess(Boolean value) { - second.addConsumer(SameThreadExecutor.INSTANCE, new DefaultResultConsumer(totalResult)); - } - - @Override - public void onFailure(Throwable t) { - totalResult.setException(t); - } - }); - return totalResult; + boolean result = + fileSet.isEmpty() || processPsiFileRoots(new ArrayList(fileSet), fileSet.size(), 0, progress, localProcessor); + if (progress != null) { + progress.popState(); + } + return result; } /** @@ -315,20 +257,19 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { * @param totalSize the number of files to scan in both passes. Can be different from files.size() in case of * two-pass scan, where we first scan files containing container name and then all the rest files. * @param alreadyProcessedFiles the number of files scanned in previous pass. + * @return true if completed */ - @NotNull - private AsyncFuture processPsiFileRootsAsync(@NotNull List files, - final int totalSize, - int alreadyProcessedFiles, - final ProgressIndicator progress, - @NotNull final Processor localProcessor) { + private boolean processPsiFileRoots(@NotNull List files, + final int totalSize, + int alreadyProcessedFiles, + final ProgressIndicator progress, + @NotNull final Processor localProcessor) { myManager.startBatchFilesProcessingMode(); - final AtomicInteger counter = new AtomicInteger(alreadyProcessedFiles); - final AtomicBoolean canceled = new AtomicBoolean(false); - - AsyncFutureResult asyncFutureResult = AsyncFutureFactory.getInstance().createAsyncFutureResult(); - final List failedFiles = Collections.synchronizedList(new SmartList()); try { + final AtomicInteger counter = new AtomicInteger(alreadyProcessedFiles); + final AtomicBoolean canceled = new AtomicBoolean(false); + + final List failedFiles = Collections.synchronizedList(new SmartList()); boolean completed = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(files, progress, false, false, new Processor() { @Override @@ -357,14 +298,12 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { }); } } - asyncFutureResult.set(completed); + return completed; + } + finally { myManager.finishBatchFilesProcessingMode(); } - catch (Throwable t) { - asyncFutureResult.setException(t); - } - return asyncFutureResult; } private void processVirtualFile(@NotNull final VirtualFile vfile, @@ -423,9 +362,6 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { if (progress != null) { progress.checkCanceled(); } - else { - ProgressManager.checkCanceled(); - } } private void getFilesWithText(@NotNull GlobalSearchScope scope, @@ -648,65 +584,32 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { final Map> collectors = ContainerUtil.newHashMap(); collectors.put(collector, processor); + ProgressIndicator progress = ProgressIndicatorProvider.getGlobalProgressIndicator(); appendCollectorsFromQueryRequests(collectors); - - final ProgressIndicator progress = ProgressIndicatorProvider.getGlobalProgressIndicator(); - final DoWhile doWhile = new DoWhile() { - @NotNull - @Override - protected AsyncFuture body() { - final AsyncFutureResult result = AsyncFutureFactory.getInstance().createAsyncFutureResult(); - MultiMap, RequestWithProcessor> globals = new MultiMap, RequestWithProcessor>(); - final List> customs = ContainerUtil.newArrayList(); - final Set locals = ContainerUtil.newLinkedHashSet(); - Map> localProcessors = new THashMap>(); - distributePrimitives(collectors, locals, globals, customs, localProcessors, progress); - AsyncFuture future = processGlobalRequestsOptimizedAsync(globals, progress, localProcessors); - future.addConsumer(SameThreadExecutor.INSTANCE, new DefaultResultConsumer(result) { - @Override - public void onSuccess(Boolean value) { - if (!value.booleanValue()) { - result.set(value); - } - else { - final Iterate iterate = new Iterate(locals) { - @NotNull - @Override - protected AsyncFuture process(RequestWithProcessor local) { - return processSingleRequestAsync(local.request, local.refProcessor); - } - }; - - iterate.getResult() - .addConsumer(SameThreadExecutor.INSTANCE, new DefaultResultConsumer(result) { - @Override - public void onSuccess(Boolean value) { - if (!value.booleanValue()) { - result.set(false); - return; - } - for (Computable custom : customs) { - if (!custom.compute()) { - result.set(false); - return; - } - } - result.set(true); - } - }); - } + boolean result; + do { + MultiMap, RequestWithProcessor> globals = new MultiMap, RequestWithProcessor>(); + final List> customs = ContainerUtil.newArrayList(); + final Set locals = ContainerUtil.newLinkedHashSet(); + Map> localProcessors = new THashMap>(); + distributePrimitives(collectors, locals, globals, customs, localProcessors, progress); + result = processGlobalRequestsOptimized(globals, progress, localProcessors); + if (result) { + for (RequestWithProcessor local : locals) { + result = processSingleRequest(local.request, local.refProcessor); + if (!result) break; + } + if (result) { + for (Computable custom : customs) { + result = custom.compute(); + if (!result) break; } - }); - return result; + } + if (!result) break; } - - @Override - protected boolean condition() { - return appendCollectorsFromQueryRequests(collectors); - } - }; - - return doWhile.getResult(); + } + while(appendCollectorsFromQueryRequests(collectors)); + return AsyncUtil.wrapBoolean(result); } private static boolean appendCollectorsFromQueryRequests(@NotNull Map> collectors) { @@ -725,19 +628,18 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { return changed; } - @NotNull - private AsyncFuture processGlobalRequestsOptimizedAsync(@NotNull MultiMap, RequestWithProcessor> singles, - final ProgressIndicator progress, - @NotNull final Map> localProcessors) { + private boolean processGlobalRequestsOptimized(@NotNull MultiMap, RequestWithProcessor> singles, + final ProgressIndicator progress, + @NotNull final Map> localProcessors) { if (singles.isEmpty()) { - return AsyncFutureFactory.wrap(true); + return true; } if (singles.size() == 1) { final Collection requests = singles.values(); if (requests.size() == 1) { final RequestWithProcessor theOnly = requests.iterator().next(); - return processSingleRequestAsync(theOnly.request, theOnly.refProcessor); + return processSingleRequest(theOnly.request, theOnly.refProcessor); } } @@ -745,64 +647,55 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { progress.pushState(); progress.setText(PsiBundle.message("psi.scanning.files.progress")); } + boolean result; - // intersectionCandidateFiles holds files containing words from all requests in `singles` and words in corresponding container names - final MultiMap intersectionCandidateFiles = createMultiMap(); - // restCandidateFiles holds files containing words from all requests in `singles` but EXCLUDING words in corresponding container names - final MultiMap restCandidateFiles = createMultiMap(); - collectFiles(singles, progress, intersectionCandidateFiles, restCandidateFiles); + try { + // intersectionCandidateFiles holds files containing words from all requests in `singles` and words in corresponding container names + final MultiMap intersectionCandidateFiles = createMultiMap(); + // restCandidateFiles holds files containing words from all requests in `singles` but EXCLUDING words in corresponding container names + final MultiMap restCandidateFiles = createMultiMap(); + collectFiles(singles, progress, intersectionCandidateFiles, restCandidateFiles); - if (intersectionCandidateFiles.isEmpty() && restCandidateFiles.isEmpty()) { - return AsyncFutureFactory.wrap(true); - } - - if (progress != null) { - final Set allWords = new TreeSet(); - for (RequestWithProcessor singleRequest : localProcessors.keySet()) { - allWords.add(singleRequest.request.word); + if (intersectionCandidateFiles.isEmpty() && restCandidateFiles.isEmpty()) { + return true; } - progress.setText(PsiBundle.message("psi.search.for.word.progress", getPresentableWordsDescription(allWords))); - } - AsyncFuture result; - if (intersectionCandidateFiles.isEmpty()) { - result = processCandidatesAsync(progress, localProcessors, restCandidateFiles, restCandidateFiles.size(), 0); - } - else { - int totalSize = restCandidateFiles.size() + intersectionCandidateFiles.size(); - AsyncFuture intersectionResult = processCandidatesAsync(progress, localProcessors, intersectionCandidateFiles, totalSize, 0); - try { - if (intersectionResult.get()) { - AsyncFuture restResult = processCandidatesAsync(progress, localProcessors, restCandidateFiles, totalSize, intersectionCandidateFiles.size()); - result = bind(intersectionResult, restResult); + if (progress != null) { + final Set allWords = new TreeSet(); + for (RequestWithProcessor singleRequest : localProcessors.keySet()) { + allWords.add(singleRequest.request.word); } - else { - result = intersectionResult; + progress.setText(PsiBundle.message("psi.search.for.word.progress", getPresentableWordsDescription(allWords))); + } + + if (intersectionCandidateFiles.isEmpty()) { + result = processCandidates(progress, localProcessors, restCandidateFiles, restCandidateFiles.size(), 0); + } + else { + int totalSize = restCandidateFiles.size() + intersectionCandidateFiles.size(); + result = processCandidates(progress, localProcessors, intersectionCandidateFiles, totalSize, 0); + if (result) { + result = processCandidates(progress, localProcessors, restCandidateFiles, totalSize, intersectionCandidateFiles.size()); } } - catch (ExecutionException e) { - Throwable cause = e.getCause(); - if (cause instanceof RuntimeException) throw (RuntimeException)cause; - if (cause instanceof Error) throw (Error)cause; - result = AsyncFutureFactory.wrapException(cause); - } - catch (InterruptedException e) { - result = AsyncFutureFactory.wrapException(e); + } + finally { + if (progress != null) { + progress.popState(); } } - return popStateAfter(result, progress); + return result; } - @NotNull - private AsyncFuture processCandidatesAsync(final ProgressIndicator progress, - @NotNull final Map> localProcessors, - @NotNull final MultiMap candidateFiles, - int totalSize, - int alreadyProcessedFiles) { + private boolean processCandidates(final ProgressIndicator progress, + @NotNull final Map> localProcessors, + @NotNull final MultiMap candidateFiles, + int totalSize, + int alreadyProcessedFiles) { List files = new ArrayList(candidateFiles.keySet()); - return processPsiFileRootsAsync(files, totalSize, alreadyProcessedFiles, progress, new Processor() { + return processPsiFileRoots(files, totalSize, alreadyProcessedFiles, progress, new Processor() { @Override public boolean process(final PsiFile psiRoot) { return ApplicationUtil.tryRunReadAction(new Computable() { @@ -1023,10 +916,9 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { collection.add(singleRequest); } - @NotNull - private AsyncFuture processSingleRequestAsync(@NotNull PsiSearchRequest single, @NotNull Processor consumer) { - return processElementsWithWordAsync(adaptProcessor(single, consumer), single.searchScope, single.word, single.searchContext, - single.caseSensitive, shouldProcessInjectedPsi(single.searchScope), single.containerName); + private boolean processSingleRequest(@NotNull PsiSearchRequest single, @NotNull Processor consumer) { + return processElementsWithWord(adaptProcessor(single, consumer), single.searchScope, single.word, single.searchContext, + single.caseSensitive, shouldProcessInjectedPsi(single.searchScope), single.containerName); } @NotNull diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java index 653f6b51e8bd..282f44d04a60 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java @@ -214,7 +214,7 @@ public class ManageCodeStyleSchemesDialog extends DialogWrapper { return !file.isDirectory() && importer.getSourceExtension().equals(file.getExtension()); } }, null, myContentPane); - VirtualFile[] selection = fileChooser.choose(CodeStyleSchemesUIConfiguration.Util.getRecentImportFile(), null); + VirtualFile[] selection = fileChooser.choose(null, CodeStyleSchemesUIConfiguration.Util.getRecentImportFile()); if (selection.length == 1) { VirtualFile selectedFile = selection[0]; selectedFile.refresh(false, false); diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java index c109de7a00a9..5da112b375b9 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionBase.java @@ -62,7 +62,7 @@ public abstract class GotoActionBase extends AnAction { private int myHistoryIndex = 0; @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { LOG.assertTrue(!getClass().equals(myInAction)); try { myInAction = getClass(); @@ -79,7 +79,7 @@ public abstract class GotoActionBase extends AnAction { protected abstract void gotoActionPerformed(AnActionEvent e); @Override - public void update(final AnActionEvent event) { + public void update(@NotNull final AnActionEvent event) { final Presentation presentation = event.getPresentation(); final DataContext dataContext = event.getDataContext(); final Project project = CommonDataKeys.PROJECT.getData(dataContext); @@ -260,7 +260,7 @@ public abstract class GotoActionBase extends AnAction { abstract class HistoryAction extends DumbAwareAction { @Override - public void update(AnActionEvent e) { + public void update(@NotNull AnActionEvent e) { e.getPresentation().setEnabled(historyEnabled()); } @@ -277,7 +277,7 @@ public abstract class GotoActionBase extends AnAction { new HistoryAction() { @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { List strings = ourHistory.get(myInAction); setText(strings); myHistoryIndex = myHistoryIndex >= strings.size() - 1 ? 0 : myHistoryIndex + 1; @@ -287,7 +287,7 @@ public abstract class GotoActionBase extends AnAction { new HistoryAction() { @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { List strings = ourHistory.get(myInAction); setText(strings); myHistoryIndex = myHistoryIndex <= 0 ? strings.size() - 1 : myHistoryIndex - 1; diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java index 3fe38cea2ed3..e0a0d946c9c5 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarListener.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,6 +18,8 @@ package com.intellij.ide.navigationToolbar; import com.intellij.ProjectTopics; import com.intellij.ide.actions.CopyAction; import com.intellij.ide.actions.CutAction; +import com.intellij.ide.ui.LafManager; +import com.intellij.ide.ui.LafManagerListener; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.AnActionListener; @@ -57,7 +59,8 @@ import java.util.List; */ public class NavBarListener extends WolfTheProblemSolver.ProblemListener implements ActionListener, FocusListener, FileStatusListener, AnActionListener, FileEditorManagerListener, - PsiTreeChangeListener, ModuleRootListener, NavBarModelListener, PropertyChangeListener, KeyListener, WindowFocusListener { + PsiTreeChangeListener, ModuleRootListener, NavBarModelListener, PropertyChangeListener, KeyListener, WindowFocusListener, + LafManagerListener { private static final String LISTENER = "NavBarListener"; private static final String BUS = "NavBarMessageBus"; private final NavBarPanel myPanel; @@ -89,6 +92,8 @@ public class NavBarListener extends WolfTheProblemSolver.ProblemListener if (window != null) { window.addWindowFocusListener(listener); } + } else { + LafManager.getInstance().addLafManagerListener(listener); } } @@ -107,6 +112,7 @@ public class NavBarListener extends WolfTheProblemSolver.ProblemListener if (connection != null) { connection.disconnect(); } + LafManager.getInstance().removeLafManagerListener(listener); } } @@ -356,15 +362,19 @@ public class NavBarListener extends WolfTheProblemSolver.ProblemListener } @Override - public void windowLostFocus(WindowEvent e) { - final Window window = e.getWindow(); - final Window oppositeWindow = e.getOppositeWindow(); + public void lookAndFeelChanged(LafManager source) { + myPanel.getNavBarUI().clearItems(); + myPanel.revalidate(); + myPanel.repaint(); } + //---- Ignored @Override - public void windowGainedFocus(WindowEvent e) { - } + public void windowLostFocus(WindowEvent e) {} + + @Override + public void windowGainedFocus(WindowEvent e) {} @Override public void keyTyped(KeyEvent e) {} diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/ui/AbstractNavBarUI.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/ui/AbstractNavBarUI.java index 1201e146869d..5e0f6e58d106 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/ui/AbstractNavBarUI.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/ui/AbstractNavBarUI.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 @@ import java.util.Map; */ public abstract class AbstractNavBarUI implements NavBarUI { - private final Map> myCache = new THashMap>(); + private final static Map> myCache = new THashMap>(); private enum ImageType { INACTIVE, NEXT_ACTIVE, ACTIVE, INACTIVE_FLOATING, NEXT_ACTIVE_FLOATING, ACTIVE_FLOATING, diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java index eb03fa86fdab..c109c8c0e14d 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java @@ -25,10 +25,10 @@ import com.intellij.openapi.module.impl.ModuleImpl; import com.intellij.openapi.project.impl.ProjectImpl; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.io.fs.IFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -102,15 +102,13 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { @NotNull @Override - public List getAllStorageFiles(final boolean includingSubStructures) { - final List result = super.getAllStorageFiles(includingSubStructures); - + public List getAllStorageFiles(final boolean includingSubStructures) { + List result = super.getAllStorageFiles(includingSubStructures); if (includingSubStructures) { for (SaveSession moduleSaveSession : myModuleSaveSessions) { result.addAll(moduleSaveSession.getAllStorageFiles(true)); } } - return result; } @@ -172,10 +170,9 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { } @Override - protected void collectSubfilesToSave(final List result) throws IOException { + protected void collectSubFilesToSave(final List result) throws IOException { for (SaveSession moduleSaveSession : myModuleSaveSessions) { - final List moduleFiles = moduleSaveSession.getAllStorageFilesToSave(true); - result.addAll(moduleFiles); + result.addAll(moduleSaveSession.getAllStorageFilesToSave(true)); } } } diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java index 7713734d07de..eaed20f2960d 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/PsiAwareFileEditorManagerImpl.java @@ -102,8 +102,9 @@ public class PsiAwareFileEditorManagerImpl extends FileEditorManagerImpl { return myProblemSolver.isProblemFile(file); } + @NotNull @Override - public String getFileTooltipText(final VirtualFile file) { + public String getFileTooltipText(@NotNull final VirtualFile file) { final StringBuilder tooltipText = new StringBuilder(); final Module module = ModuleUtilCore.findModuleForFile(file, getProject()); if (module != null) { @@ -116,7 +117,7 @@ public class PsiAwareFileEditorManagerImpl extends FileEditorManagerImpl { } @Override - protected Editor getOpenedEditor(final Editor editor, final boolean focusEditor) { + protected Editor getOpenedEditor(@NotNull final Editor editor, final boolean focusEditor) { PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject()); Document document = editor.getDocument(); PsiFile psiFile = documentManager.getPsiFile(document); @@ -200,7 +201,7 @@ public class PsiAwareFileEditorManagerImpl extends FileEditorManagerImpl { updateFile(file); } - private void updateFile(final VirtualFile file) { + private void updateFile(@NotNull VirtualFile file) { queueUpdateFile(file); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/TestEditorManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/TestEditorManagerImpl.java index 79ac777a6fd8..958daee0098a 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/TestEditorManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/TestEditorManagerImpl.java @@ -38,6 +38,7 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.testFramework.LightVirtualFile; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashMap; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -195,7 +196,7 @@ public class TestEditorManagerImpl extends FileEditorManagerEx implements Applic return openTextEditor(descriptor, false); } - private FileEditorProvider getProvider(FileEditor editor) { + private static FileEditorProvider getProvider(FileEditor editor) { return new FileEditorProvider() { @Override public boolean accept(@NotNull Project project, @NotNull VirtualFile file) { @@ -205,18 +206,17 @@ public class TestEditorManagerImpl extends FileEditorManagerEx implements Applic @Override @NotNull public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) { - return null; + throw new IncorrectOperationException(); } @Override public void disposeEditor(@NotNull FileEditor editor) { - //Disposer.dispose(editor); } @Override @NotNull public FileEditorState readState(@NotNull Element sourceElement, @NotNull Project project, @NotNull VirtualFile file) { - return null; + throw new IncorrectOperationException(); } @Override @@ -233,7 +233,7 @@ public class TestEditorManagerImpl extends FileEditorManagerEx implements Applic @Override @NotNull public FileEditorPolicy getPolicy() { - return null; + throw new IncorrectOperationException(); } }; } @@ -482,7 +482,7 @@ public class TestEditorManagerImpl extends FileEditorManagerEx implements Applic @NotNull @Override public EditorsSplitters getSplitters() { - return null; + throw new IncorrectOperationException(); } @NotNull @@ -492,6 +492,6 @@ public class TestEditorManagerImpl extends FileEditorManagerEx implements Applic } @Override - public void setSelectedEditor(@NotNull VirtualFile file, String fileEditorProviderId) { + public void setSelectedEditor(@NotNull VirtualFile file, @NotNull String fileEditorProviderId) { } } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java index b1f034d2dcb2..8f197a4950f8 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java @@ -39,8 +39,6 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.tracker.VirtualFileTracker; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.io.fs.FileSystem; -import com.intellij.util.io.fs.IFile; import com.intellij.util.messages.MessageBus; import org.jdom.Element; import org.jetbrains.annotations.Nls; @@ -192,10 +190,9 @@ public class ClasspathStorage implements StateStorage { return session; } - private static void convert2Io(List list, ArrayList virtualFiles) { + private static void convert2Io(List list, ArrayList virtualFiles) { for (VirtualFile virtualFile : virtualFiles) { - final File ioFile = VfsUtilCore.virtualToIoFile(virtualFile); - list.add(FileSystem.FILE_SYSTEM.createFile(ioFile.getAbsolutePath())); + list.add(VfsUtilCore.virtualToIoFile(virtualFile)); } } @@ -384,12 +381,12 @@ public class ClasspathStorage implements StateStorage { } @Override - public Set getClasspath(final ModifiableRootModel model, final Element element) throws IOException, InvalidDataException { + public Set getClasspath(final ModifiableRootModel model, final Element element) throws InvalidDataException { throw new InvalidDataException(getDescription()); } @Override - public void setClasspath(ModuleRootModel model) throws IOException, WriteExternalException { + public void setClasspath(ModuleRootModel model) throws WriteExternalException { throw new WriteExternalException(getDescription()); } }; @@ -426,9 +423,9 @@ public class ClasspathStorage implements StateStorage { @NotNull @Override - public Collection getStorageFilesToSave() throws StateStorageException { + public Collection getStorageFilesToSave() throws StateStorageException { if (needsSave()) { - final List list = new ArrayList(); + final List list = new ArrayList(); final ArrayList virtualFiles = new ArrayList(); getFileSet().listModifiedFiles(virtualFiles); convert2Io(list, virtualFiles); @@ -441,9 +438,9 @@ public class ClasspathStorage implements StateStorage { @NotNull @Override - public List getAllStorageFiles() { - final List list = new ArrayList(); - final ArrayList virtualFiles = new ArrayList(); + public List getAllStorageFiles() { + List list = new ArrayList(); + ArrayList virtualFiles = new ArrayList(); getFileSet().listFiles(virtualFiles); convert2Io(list, virtualFiles); return list; diff --git a/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java b/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java index 65f2d758fcfd..a30ccd677682 100644 --- a/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java +++ b/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java @@ -471,9 +471,10 @@ public class RegistryUi implements Disposable { public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { myValue = ((MyTableModel)table.getModel()).getRegistryValue(row); if (myValue.asColor(null) != null) { - final Color color = ColorChooser.chooseColor(table, "Choose color", ((RegistryValue)value).asColor(Color.WHITE)); + final Color color = ColorChooser.chooseColor(table, "Choose color", myValue.asColor(Color.WHITE)); if (color != null) { myValue.setValue(color.getRed() + "," + color.getGreen() + "," + color.getBlue()); + keyChanged(myValue.getKey()); } return null; } else if (myValue.isBoolean()) { diff --git a/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java b/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java index bbffc7c98ba4..02ddd0b64608 100644 --- a/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java +++ b/platform/lang-impl/src/com/intellij/platform/templates/github/DownloadUtil.java @@ -1,5 +1,6 @@ package com.intellij.platform.templates.github; +import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -19,7 +20,6 @@ import java.net.HttpURLConnection; import java.net.URLConnection; import java.util.Locale; import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; /** * @author Sergey Simonchik @@ -176,6 +176,7 @@ public class DownloadUtil { URLConnection urlConnection = HttpConfigurable.getInstance().openConnection(location); HttpURLConnection httpURLConnection = ObjectUtils.tryCast(urlConnection, HttpURLConnection.class); try { + urlConnection.setRequestProperty("User-Agent", ApplicationInfoEx.getInstanceEx().getFullApplicationName()); urlConnection.connect(); InputStream in = urlConnection.getInputStream(); int contentLength = urlConnection.getContentLength(); diff --git a/platform/lang-impl/src/com/intellij/ui/tabs/EditorTabColorProviderImpl.java b/platform/lang-impl/src/com/intellij/ui/tabs/EditorTabColorProviderImpl.java index 93ebe1f0573a..5c2083710f2a 100644 --- a/platform/lang-impl/src/com/intellij/ui/tabs/EditorTabColorProviderImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/tabs/EditorTabColorProviderImpl.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. @@ -20,6 +20,7 @@ import com.intellij.openapi.fileEditor.impl.EditorTabColorProvider; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.FileColorManager; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; @@ -31,7 +32,7 @@ public class EditorTabColorProviderImpl implements EditorTabColorProvider { @Override @Nullable - public Color getEditorTabColor(Project project, VirtualFile file) { + public Color getEditorTabColor(@NotNull Project project, @NotNull VirtualFile file) { FileColorManager colorManager = FileColorManager.getInstance(project); return colorManager.isEnabledForTabs() ? colorManager.getFileColor(file) : null; } diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/Separator.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/Separator.java index 2dd2ee50d120..191c8c01ce32 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/Separator.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/Separator.java @@ -41,6 +41,11 @@ public final class Separator extends AnAction implements DumbAware { return ourInstance; } + @Override + public String toString() { + return "Separator (" + myText + ")"; + } + @Override public void actionPerformed(AnActionEvent e){ throw new UnsupportedOperationException(); diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java index 9e0bf738a7cf..fee268813d14 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java +++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooser.java @@ -52,7 +52,7 @@ public class FileChooser { @Nullable final Project project, @Nullable final VirtualFile toSelect) { final FileChooserDialog chooser = FileChooserFactory.getInstance().createFileChooser(descriptor, project, parent); - return chooser.choose(toSelect, project); + return chooser.choose(project, toSelect); } @Nullable diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java index 86e719eef48d..dcb1327f1a10 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java @@ -197,5 +197,5 @@ public abstract class FileEditorManager { * @param fileEditorProviderId the ID of the file editor to open; matches the return value of * {@link com.intellij.openapi.fileEditor.FileEditorProvider#getEditorTypeId()} */ - public abstract void setSelectedEditor(@NotNull VirtualFile file, String fileEditorProviderId); + public abstract void setSelectedEditor(@NotNull VirtualFile file, @NotNull String fileEditorProviderId); } diff --git a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java index 78a4c1ece130..828907c13cfb 100644 --- a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java +++ b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java @@ -175,9 +175,25 @@ public class ConfigurableEP extends AbstractExten return getDisplayName(); } + public boolean canCreateConfigurable() { + if (providerClass == null) { + return implementationClass != null || instanceClass != null; + } + try { + ConfigurableProvider provider = instantiate(providerClass, myPicoContainer); + return provider.canCreateConfigurable(); // do not load heavy configurables + } + catch (Exception ignored) { + return true; // see InstanceFromProviderFactory#compute + } + } + private class InstanceFromProviderFactory extends AtomicNotNullLazyValue implements NullableFactory { public T create() { - return (T)getValue().createConfigurable(); + ConfigurableProvider provider = getValue(); + return provider.canCreateConfigurable() + ? (T)provider.createConfigurable() + : null; } @NotNull diff --git a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableProvider.java b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableProvider.java index 5a71ffa73050..cf2bc0390c5a 100644 --- a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableProvider.java +++ b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableProvider.java @@ -29,4 +29,15 @@ public abstract class ConfigurableProvider { @Nullable public abstract Configurable createConfigurable(); + /** + * Defines whether this provider creates a configurable or not. + * Note that the {@code createConfigurable} method will be called + * if this method returns {@code true}. + * + * @return {@code true} if this provider creates configurable, + * {@code false} otherwise + */ + public boolean canCreateConfigurable() { + return true; + } } diff --git a/platform/platform-api/src/com/intellij/openapi/options/SearchableConfigurable.java b/platform/platform-api/src/com/intellij/openapi/options/SearchableConfigurable.java index e98bb05aba99..b426e35d77a8 100644 --- a/platform/platform-api/src/com/intellij/openapi/options/SearchableConfigurable.java +++ b/platform/platform-api/src/com/intellij/openapi/options/SearchableConfigurable.java @@ -34,6 +34,12 @@ public interface SearchableConfigurable extends Configurable { interface Parent extends SearchableConfigurable, Composite { boolean hasOwnContent(); + + /** + * @deprecated use {@link ConfigurableProvider#canCreateConfigurable()} instead + * to specify configurables which should not be visible + */ + @Deprecated boolean isVisible(); abstract class Abstract implements Parent { diff --git a/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java b/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java index 129217ec7e4a..0416008d1d57 100644 --- a/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java +++ b/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java @@ -204,6 +204,8 @@ public class LinkLabel extends JLabel { } private boolean isInClickableArea(Point pt) { + Insets insets = getInsets(); // border is set + pt.translate(-insets.left, -insets.top); if (getIcon() != null) { if (pt.getX() < getIcon().getIconWidth() && pt.getY() < getIcon().getIconHeight()) { return true; diff --git a/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java b/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java index b33611da8866..876474b9124b 100644 --- a/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java +++ b/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java @@ -146,19 +146,11 @@ public class JobLauncherImpl extends JobLauncher { // This implementation is not really async @NotNull @Override - public AsyncFutureResult invokeConcurrentlyUnderProgressAsync(@NotNull List things, + public AsyncFuture invokeConcurrentlyUnderProgressAsync(@NotNull List things, ProgressIndicator progress, boolean failFastOnAcquireReadAction, @NotNull Processor thingProcessor) { - final AsyncFutureResult asyncFutureResult = AsyncFutureFactory.getInstance().createAsyncFutureResult(); - try { - final boolean result = invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor); - asyncFutureResult.set(result); - } - catch (Throwable t) { - asyncFutureResult.setException(t); - } - return asyncFutureResult; + return AsyncUtil.wrapBoolean(invokeConcurrentlyUnderProgress(things, progress, failFastOnAcquireReadAction, thingProcessor)); } @NotNull diff --git a/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java b/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java index 4189b6adf98b..cf10681f82a5 100644 --- a/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java +++ b/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java @@ -36,15 +36,15 @@ import org.jetbrains.annotations.Nullable; name = "RecentDirectoryProjectsManager", roamingType = RoamingType.DISABLED, storages = { - @Storage( - file = StoragePathMacros.APP_CONFIG + "/other.xml" - )} + @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml") + } ) public class RecentDirectoryProjectsManager extends RecentProjectsManagerBase { public RecentDirectoryProjectsManager(MessageBus messageBus) { super(messageBus); } + @Override @Nullable protected String getProjectPath(@NotNull Project project) { final ProjectBaseDirectory baseDir = ProjectBaseDirectory.getInstance(project); @@ -52,6 +52,7 @@ public class RecentDirectoryProjectsManager extends RecentProjectsManagerBase { return baseDirVFile != null ? FileUtil.toSystemDependentName(baseDirVFile.getPath()) : null; } + @Override protected void doOpenProject(@NotNull String projectPath, Project projectToClose, boolean forceOpenInNewFrame) { final VirtualFile projectDir = LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(projectPath)); if (projectDir != null) { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java index 442d09b8b3bd..505d0f5eef3d 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/BaseShowRecentFilesAction.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. @@ -39,6 +39,7 @@ import com.intellij.ui.components.JBList; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import com.intellij.util.IconUtil; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.event.ListSelectionEvent; @@ -53,11 +54,11 @@ import java.io.File; public abstract class BaseShowRecentFilesAction extends AnAction implements DumbAware { private static final Color BORDER_COLOR = Gray._135; - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { show(CommonDataKeys.PROJECT.getData(e.getDataContext())); } - public void update(AnActionEvent event){ + public void update(@NotNull AnActionEvent event){ Presentation presentation = event.getPresentation(); Project project = CommonDataKeys.PROJECT.getData(event.getDataContext()); presentation.setEnabled(project != null); @@ -93,7 +94,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb final JList list = new JBList(model); list.addKeyListener( new KeyAdapter() { - public void keyPressed(KeyEvent e) { + public void keyPressed(@NotNull KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_DELETE) { int index = list.getSelectedIndex(); if (index == -1 || index >= list.getModel().getSize()){ @@ -150,7 +151,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb JPanel footerPanel = new JPanel(new BorderLayout()) { @Override - protected void paintComponent(Graphics g) { + protected void paintComponent(@NotNull Graphics g) { super.paintComponent(g); g.setColor(BORDER_COLOR); g.drawLine(0, 0, getWidth(), 0); @@ -237,7 +238,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb } @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(@NotNull ActionEvent e) { if (myPopup != null) { myPopup.cancel(); } @@ -272,7 +273,7 @@ public abstract class BaseShowRecentFilesAction extends AnAction implements Dumb return fullText; } - public void valueChanged(final ListSelectionEvent e) { + public void valueChanged(@NotNull final ListSelectionEvent e) { //noinspection SSBasedInspection SwingUtilities.invokeLater(new Runnable() { public void run() { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java index 59ac567af38a..abd875af728f 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.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. @@ -25,13 +25,14 @@ import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; /** * @author Konstantin Bulenkov */ public class ShowRecentFilesAction extends DumbAwareAction { @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { final Project project = e.getData(CommonDataKeys.PROJECT); if (project != null) { FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.recent.files"); diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java index cb35b5a504f9..cecf0f60a803 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java @@ -94,7 +94,7 @@ public class Switcher extends AnAction implements DumbAware { public void run() { synchronized (Switcher.class) { if (SWITCHER != null) { - SWITCHER.navigate(); + SWITCHER.navigate(false); } } } @@ -135,7 +135,7 @@ public class Switcher extends AnAction implements DumbAware { @NonNls private static final String SWITCHER_TITLE = "Switcher"; - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); if (project == null) return; @@ -200,7 +200,7 @@ public class Switcher extends AnAction implements DumbAware { jList.setSelectedIndex(jList.getAnchorSelectionIndex()); } if (jList.getSelectedIndex() != -1) { - navigate(); + navigate(false); } } return true; @@ -226,7 +226,7 @@ public class Switcher extends AnAction implements DumbAware { descriptions = new JPanel(new BorderLayout()) { @Override - protected void paintComponent(Graphics g) { + protected void paintComponent(@NotNull Graphics g) { super.paintComponent(g); g.setColor(UIUtil.isUnderDarcula() ? SEPARATOR_COLOR : BORDER_COLOR); g.drawLine(0, 0, getWidth(), 0); @@ -249,7 +249,7 @@ public class Switcher extends AnAction implements DumbAware { final Map map = ContainerUtil.reverseMap(twShortcuts); Collections.sort(windows, new Comparator() { @Override - public int compare(ToolWindow o1, ToolWindow o2) { + public int compare(@NotNull ToolWindow o1, @NotNull ToolWindow o2) { return StringUtil.compare(map.get(o1), map.get(o2), false); } }); @@ -297,7 +297,7 @@ public class Switcher extends AnAction implements DumbAware { toolWindows.addMouseMotionListener(this); myClickListener.installOn(toolWindows); toolWindows.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { + public void valueChanged(@NotNull ListSelectionEvent e) { if (!toolWindows.isSelectionEmpty() && !files.isSelectionEmpty()) { files.clearSelection(); } @@ -306,7 +306,7 @@ public class Switcher extends AnAction implements DumbAware { separator = new JPanel() { @Override - protected void paintComponent(Graphics g) { + protected void paintComponent(@NotNull Graphics g) { super.paintComponent(g); g.setColor(SEPARATOR_COLOR); g.drawLine(0, 0, 0, getHeight()); @@ -374,7 +374,7 @@ public class Switcher extends AnAction implements DumbAware { JPanel myPanel = new JPanel(new BorderLayout()); JLabel myLabel = new JLabel() { @Override - protected void paintComponent(Graphics g) { + protected void paintComponent(@NotNull Graphics g) { GraphicsConfig config = new GraphicsConfig(g); ((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f)); super.paintComponent(g); @@ -425,7 +425,7 @@ public class Switcher extends AnAction implements DumbAware { return fullText; } - public void valueChanged(final ListSelectionEvent e) { + public void valueChanged(@NotNull final ListSelectionEvent e) { ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { updatePathLabel(); @@ -466,7 +466,7 @@ public class Switcher extends AnAction implements DumbAware { files.setSelectionMode(pinned ? ListSelectionModel.MULTIPLE_INTERVAL_SELECTION : ListSelectionModel.SINGLE_SELECTION); files.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { + public void valueChanged(@NotNull ListSelectionEvent e) { if (!files.isSelectionEmpty() && !toolWindows.isSelectionEmpty()) { toolWindows.getSelectionModel().clearSelection(); } @@ -526,21 +526,21 @@ public class Switcher extends AnAction implements DumbAware { if (isPinnedMode()) { new AnAction(null ,null ,null) { @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { changeSelection(); } }.registerCustomShortcutSet(CustomShortcutSet.fromString("TAB"), this, myPopup); new AnAction(null, null, null) { @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { //suppress all actions to activate a toolwindow : IDEA-71277 } }.registerCustomShortcutSet(TW_SHORTCUT, this, myPopup); new AnAction(null, null, null) { @Override - public void actionPerformed(AnActionEvent e) { + public void actionPerformed(@NotNull AnActionEvent e) { if (mySpeedSearch != null && mySpeedSearch.isPopupActive()) { mySpeedSearch.hidePopup(); } else { @@ -590,24 +590,24 @@ public class Switcher extends AnAction implements DumbAware { return ((KeyboardShortcut)shortcutSet.getShortcuts()[0]).getFirstKeyStroke().getModifiers(); } - public void keyTyped(KeyEvent e) { + public void keyTyped(@NotNull KeyEvent e) { } public void keyReleased(KeyEvent e) { - if ((e.getKeyCode() == CTRL_KEY && isAutoHide()) - || e.getKeyCode() == VK_ENTER) { - navigate(); - } else - if (e.getKeyCode() == VK_LEFT) { + if (e.getKeyCode() == CTRL_KEY && isAutoHide() || e.getKeyCode() == VK_ENTER) { + navigate(e.isShiftDown()); + } + else if (e.getKeyCode() == VK_LEFT) { goLeft(); - } else if (e.getKeyCode() == VK_RIGHT) { + } + else if (e.getKeyCode() == VK_RIGHT) { goRight(); } } KeyEvent lastEvent; - public void keyPressed(KeyEvent e) { - if ((mySpeedSearch != null && mySpeedSearch.isPopupActive()) || lastEvent == e) return; + public void keyPressed(@NotNull KeyEvent e) { + if (mySpeedSearch != null && mySpeedSearch.isPopupActive() || lastEvent == e) return; lastEvent = e; switch (e.getKeyCode()) { case VK_UP: @@ -668,7 +668,7 @@ public class Switcher extends AnAction implements DumbAware { if (value instanceof FileInfo) { final FileInfo info = (FileInfo)value; final VirtualFile virtualFile = info.first; - final FileEditorManagerImpl editorManager = ((FileEditorManagerImpl)FileEditorManager.getInstance(project)); + final FileEditorManagerImpl editorManager = (FileEditorManagerImpl)FileEditorManager.getInstance(project); final JList jList = getSelectedList(); final EditorWindow wnd = findAppropriateWindow(info); if (wnd == null) { @@ -836,7 +836,7 @@ public class Switcher extends AnAction implements DumbAware { } } - void navigate() { + void navigate(final boolean openInNewWindow) { final Object[] values = getSelectedList().getSelectedValues(); myPopup.closeOk(null); if (values.length > 0 && values[0] instanceof ToolWindow) { @@ -850,14 +850,19 @@ public class Switcher extends AnAction implements DumbAware { if (value instanceof FileInfo) { final FileInfo info = (FileInfo)value; - if (info.second != null) { + VirtualFile file = info.first; + if (openInNewWindow) { + manager.openFileInNewWindow(file); + } + else if (info.second != null) { EditorWindow wnd = findAppropriateWindow(info); if (wnd != null) { - manager.openFileImpl2(wnd, info.first, true); - manager.addSelectionRecord(info.first, wnd); + manager.openFileImpl2(wnd, file, true); + manager.addSelectionRecord(file, wnd); } - } else { - manager.openFile(info.first, true, true); + } + else { + manager.openFile(file, true, true); } } } @@ -873,13 +878,13 @@ public class Switcher extends AnAction implements DumbAware { return ArrayUtil.contains(info.second, windows) ? info.second : windows.length > 0 ? windows[0] : null; } - public void mouseClicked(MouseEvent e) { + public void mouseClicked(@NotNull MouseEvent e) { } private boolean mouseMovedFirstTime = true; private JList mouseMoveSrc = null; private int mouseMoveListIndex = -1; - public void mouseMoved(MouseEvent e) { + public void mouseMoved(@NotNull MouseEvent e) { if (mouseMovedFirstTime) { mouseMovedFirstTime = false; return; @@ -907,15 +912,15 @@ public class Switcher extends AnAction implements DumbAware { files.repaint(); } - public void mousePressed(MouseEvent e) {} - public void mouseReleased(MouseEvent e) {} - public void mouseEntered(MouseEvent e) {} - public void mouseExited(MouseEvent e) { + public void mousePressed(@NotNull MouseEvent e) {} + public void mouseReleased(@NotNull MouseEvent e) {} + public void mouseEntered(@NotNull MouseEvent e) {} + public void mouseExited(@NotNull MouseEvent e) { mouseMoveSrc = null; mouseMoveListIndex = -1; repaintLists(); } - public void mouseDragged(MouseEvent e) {} + public void mouseDragged(@NotNull MouseEvent e) {} private class SwitcherSpeedSearch extends SpeedSearchBase implements PropertyChangeListener { private Object[] myElements; @@ -1031,7 +1036,7 @@ public class Switcher extends AnAction implements DumbAware { } @Override - public void propertyChange(PropertyChangeEvent evt) { + public void propertyChange(@NotNull PropertyChangeEvent evt) { final MyList list = getSelectedList(); final Object value = list.getSelectedValue(); if (project.isDisposed()) { @@ -1068,7 +1073,7 @@ public class Switcher extends AnAction implements DumbAware { private Rectangle dBounds; @Override - public void layoutContainer(Container target) { + public void layoutContainer(@NotNull Container target) { final JScrollPane scrollPane = UIUtil.getParentOfType(JScrollPane.class, files); JComponent filesPane = scrollPane != null ? scrollPane : files; if (sBounds == null || !target.isShowing()) { @@ -1142,7 +1147,7 @@ public class Switcher extends AnAction implements DumbAware { } @Override - public void processKeyEvent(KeyEvent e) { + public void processKeyEvent(@NotNull KeyEvent e) { super.processKeyEvent(e); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java index 85c0555f9bc6..9af1d30c28bf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/Utils.java @@ -26,6 +26,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; @@ -164,7 +165,7 @@ public class Utils{ } } else if (child instanceof Separator) { - if (!list.isEmpty() && !(list.get(list.size() - 1) instanceof Separator)) { + if (!StringUtil.isEmpty(((Separator)child).getText()) || (!list.isEmpty() && !(list.get(list.size() - 1) instanceof Separator))) { list.add(child); } } @@ -284,8 +285,10 @@ public class Utils{ for (int i = 0, size = list.size(); i < size; i++) { final AnAction action = list.get(i); if (action instanceof Separator) { - if (i > 0 && i < size - 1) { + final String text = ((Separator)action).getText(); + if (!StringUtil.isEmpty(text) || (i > 0 && i < size - 1)) { component.add(new JPopupMenu.Separator() { + private final JMenuItem myMenu = !StringUtil.isEmpty(text) ? new JMenuItem(text) : null; @Override public Insets getInsets() { final Insets insets = super.getInsets(); @@ -295,13 +298,30 @@ public class Utils{ return fix ? new Insets(2, insets.left, 3, insets.right) : insets; // workaround for Sun bug #6636964 } + @Override + public void doLayout() { + super.doLayout(); + if (myMenu != null) { + myMenu.setBounds(getBounds()); + } + } + @Override protected void paintComponent(Graphics g) { if (UIUtil.isUnderWindowsClassicLookAndFeel() || UIUtil.isUnderDarcula() || UIUtil.isUnderWindowsLookAndFeel()) { g.setColor(component.getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); } - super.paintComponent(g); + if (myMenu != null) { + myMenu.paint(g); + } else { + super.paintComponent(g); + } + } + + @Override + public Dimension getPreferredSize() { + return myMenu != null ? myMenu.getPreferredSize() : super.getPreferredSize(); } }); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java index a00533d3244b..86ccd77be20d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ApplicationStoreImpl.java @@ -36,7 +36,6 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto private static final String XML_EXTENSION = ".xml"; private static final String DEFAULT_STORAGE_SPEC = StoragePathMacros.APP_CONFIG + "/" + PathManager.DEFAULT_OPTIONS_FILE_NAME + XML_EXTENSION; - private static final String OPTIONS_MACRO = "OPTIONS"; private static final String ROOT_ELEMENT_NAME = "application"; private final ApplicationImpl myApplication; @@ -95,7 +94,6 @@ class ApplicationStoreImpl extends ComponentStoreImpl implements IApplicationSto @Override public void setOptionsPath(final String path) { myStateStorageManager.addMacro(StoragePathMacros.getMacroName(StoragePathMacros.APP_CONFIG), path); - myStateStorageManager.addMacro(OPTIONS_MACRO, path); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index c6208e8ffc15..ed63bf12d4c4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -29,12 +29,12 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.ReflectionUtil; -import com.intellij.util.io.fs.IFile; import gnu.trove.THashMap; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.io.IOException; import java.lang.reflect.Type; import java.util.*; @@ -354,7 +354,7 @@ public abstract class ComponentStoreImpl implements IComponentStore { @NotNull @Override - public List getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException { + public List getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException { try { return myStorageManagerSaveSession.getAllStorageFilesToSave(); } @@ -443,10 +443,9 @@ public abstract class ComponentStoreImpl implements IComponentStore { @NotNull @Override - public List getAllStorageFiles(final boolean includingSubStructures) { + public List getAllStorageFiles(final boolean includingSubStructures) { return myStorageManagerSaveSession.getAllStorageFiles(); } - } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java index 51cc717726f3..aacdb58aeeec 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java @@ -18,9 +18,9 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.StateStorageException; import com.intellij.util.SmartList; -import com.intellij.util.io.fs.IFile; import gnu.trove.THashMap; +import java.io.File; import java.util.List; import java.util.Map; @@ -36,8 +36,8 @@ public class CompoundSaveSession { } } - public List getAllStorageFilesToSave() throws StateStorageException { - List result = new SmartList(); + public List getAllStorageFilesToSave() throws StateStorageException { + List result = new SmartList(); for (StateStorage.SaveSession saveSession : mySaveSessions.values()) { result.addAll(saveSession.getStorageFilesToSave()); } @@ -70,8 +70,8 @@ public class CompoundSaveSession { return mySaveSessions.get(storage); } - public List getAllStorageFiles() { - List result = new SmartList(); + public List getAllStorageFiles() { + List result = new SmartList(); for (StateStorage.SaveSession saveSession : mySaveSessions.values()) { result.addAll(saveSession.getAllStorageFiles()); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java index 03f01e291f7d..aa3635dd09c2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java @@ -21,12 +21,12 @@ import com.intellij.openapi.project.impl.ProjectImpl; import com.intellij.openapi.project.impl.ProjectManagerImpl; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.io.fs.IFile; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Collections; @@ -101,13 +101,13 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { @NotNull @Override - public Collection getStorageFilesToSave() throws StateStorageException { + public Collection getStorageFilesToSave() throws StateStorageException { return Collections.emptyList(); } @NotNull @Override - public List getAllStorageFiles() { + public List getAllStorageFiles() { return Collections.emptyList(); } } @@ -239,13 +239,13 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { @NotNull @Override - public List getAllStorageFilesToSave() throws StateStorageException { + public List getAllStorageFilesToSave() throws StateStorageException { return Collections.emptyList(); } @NotNull @Override - public List getAllStorageFiles() { + public List getAllStorageFiles() { return Collections.emptyList(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java index 8a210c321c3c..9774271e61c7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java @@ -26,7 +26,8 @@ import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.tracker.VirtualFileTracker; -import com.intellij.util.io.fs.IFile; +import com.intellij.util.SmartList; +import com.intellij.util.containers.SmartHashSet; import com.intellij.util.messages.MessageBus; import org.jdom.Element; import org.jetbrains.annotations.NotNull; @@ -37,16 +38,13 @@ import java.io.File; import java.io.IOException; import java.util.*; -import static com.intellij.util.io.fs.FileSystem.FILE_SYSTEM; - //todo: support missing plugins //todo: support storage data public class DirectoryBasedStorage implements StateStorage, Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.DirectoryBasedStorage"); - private static final IFile[] EMPTY_FILES = new IFile[0]; private final TrackingPathMacroSubstitutor myPathMacroSubstitutor; - private final IFile myDir; + private final File myDir; private final StateSplitter mySplitter; private final FileTypeManager myFileTypeManager; @@ -59,7 +57,7 @@ public class DirectoryBasedStorage implements StateStorage, Disposable { @NotNull Disposable parentDisposable, @NotNull PicoContainer picoContainer) { myPathMacroSubstitutor = pathMacroSubstitutor; - myDir = FILE_SYSTEM.createFile(dir); + myDir = new File(dir); mySplitter = splitter; Disposer.register(parentDisposable, this); @@ -180,31 +178,27 @@ public class DirectoryBasedStorage implements StateStorage, Disposable { @Override public void save() throws StateStorageException { assert mySession == this; - final Set currentNames = new HashSet(); - - IFile[] children = myDir.exists() ? myDir.listFiles() : EMPTY_FILES; - for (IFile child : children) { - final String fileName = child.getName(); - if (!myFileTypeManager.isFileIgnored(fileName) && StringUtil.endsWithIgnoreCase(fileName, ".xml")) { - currentNames.add(fileName); + final Set currentNames = new SmartHashSet(); + File[] children = myDir.listFiles(); + if (children != null) { + for (File child : children) { + final String fileName = child.getName(); + if (!myFileTypeManager.isFileIgnored(fileName) && StringUtil.endsWithIgnoreCase(fileName, ".xml")) { + currentNames.add(fileName); + } } } myStorageData.process(new DirectoryStorageData.StorageDataProcessor() { @Override - public void process(final String componentName, final IFile file, final Element element) { + public void process(final String componentName, final File file, final Element element) { currentNames.remove(file.getName()); if (myPathMacroSubstitutor != null) { myPathMacroSubstitutor.collapsePaths(element); } - if (file.getTimeStamp() <= myStorageData.getLastTimeStamp()) { - if (!myDir.exists()) { - myDir.createParentDirs(); - myDir.mkDir(); - } - + if (file.lastModified() <= myStorageData.getLastTimeStamp()) { StorageUtil.save(file, element, MySaveSession.this, false); myStorageData.updateLastTimestamp(file); } @@ -217,9 +211,8 @@ public class DirectoryBasedStorage implements StateStorage, Disposable { public void run() { if (myDir.exists()) { for (String name : currentNames) { - IFile child = myDir.getChild(name); - - if (child.getTimeStamp() > myStorageData.getLastTimeStamp()) { + File child = new File(myDir, name); + if (child.lastModified() > myStorageData.getLastTimeStamp()) { // do not touch new files during VC update (which aren't read yet) // now got an opposite problem: file is recreated if was removed by VC during update. return; @@ -272,23 +265,26 @@ public class DirectoryBasedStorage implements StateStorage, Disposable { @Override @NotNull - public Collection getStorageFilesToSave() throws StateStorageException { + public Collection getStorageFilesToSave() throws StateStorageException { assert mySession == this; if (!myDir.exists()) return getAllStorageFiles(); assert myDir.isDirectory() : myDir.getPath(); - final List filesToSave = new ArrayList(); - - IFile[] children = myDir.listFiles(); - final Set currentChildNames = new HashSet(); - for (IFile child : children) { - if (!myFileTypeManager.isFileIgnored(child.getName())) currentChildNames.add(child.getName()); + final List filesToSave = new ArrayList(); + final Set currentChildNames = new SmartHashSet(); + File[] children = myDir.listFiles(); + if (children != null) { + for (File child : children) { + if (!myFileTypeManager.isFileIgnored(child.getName())) { + currentChildNames.add(child.getName()); + } + } } myStorageData.process(new DirectoryStorageData.StorageDataProcessor() { @Override - public void process(final String componentName, final IFile file, final Element element) { + public void process(final String componentName, final File file, final Element element) { if (currentChildNames.contains(file.getName())) { currentChildNames.remove(file.getName()); @@ -305,8 +301,7 @@ public class DirectoryBasedStorage implements StateStorage, Disposable { }); for (String childName : currentChildNames) { - final IFile child = myDir.getChild(childName); - filesToSave.add(child); + filesToSave.add(new File(myDir, childName)); } return filesToSave; @@ -314,8 +309,8 @@ public class DirectoryBasedStorage implements StateStorage, Disposable { @Override @NotNull - public List getAllStorageFiles() { - return new ArrayList(myStorageData.getAllStorageFiles().keySet()); + public List getAllStorageFiles() { + return new SmartList(myStorageData.getAllStorageFiles().keySet()); } } @@ -327,13 +322,12 @@ public class DirectoryBasedStorage implements StateStorage, Disposable { } @Override - public void setState(@NotNull final Object component, final String componentName, @NotNull final Object state, final Storage storageSpec) - throws StateStorageException { + public void setState(@NotNull final Object component, final String componentName, @NotNull final Object state, final Storage storageSpec) { assert mySession == this; setState(componentName, state, storageSpec); } - private void setState(final String componentName, @NotNull Object state, final Storage storageSpec) throws StateStorageException { + private void setState(final String componentName, @NotNull Object state, final Storage storageSpec) { try { final Element element = DefaultStateSerializer.serializeState(state, storageSpec); if (element != null) { @@ -345,7 +339,7 @@ public class DirectoryBasedStorage implements StateStorage, Disposable { statePart.setAttribute(StorageData.NAME, componentName); statePart.addContent(e.detach()); - myStorageData.put(componentName, myDir.getChild(name), statePart, false); + myStorageData.put(componentName, new File(myDir, name), statePart, false); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java index 757d174f86d2..88a227168e5e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java @@ -33,8 +33,6 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.tracker.VirtualFileTracker; -import com.intellij.util.io.fs.FileSystem; -import com.intellij.util.io.fs.IFile; import com.intellij.util.messages.MessageBus; import org.jdom.Document; import org.jdom.Element; @@ -52,12 +50,12 @@ import java.util.Collections; import java.util.List; public class FileBasedStorage extends XmlElementStorage { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.FileBasedStorage"); + private static final Logger LOG = Logger.getInstance(FileBasedStorage.class); private static boolean ourConfigDirectoryRefreshed = false; private final String myFilePath; - private final IFile myFile; + private final File myFile; private final String myRootElementName; private volatile VirtualFile myCachedVirtualFile; @@ -76,16 +74,13 @@ public class FileBasedStorage extends XmlElementStorage { myRootElementName = rootElementName; myFilePath = filePath; - myFile = FileSystem.FILE_SYSTEM.createFile(myFilePath); + myFile = new File(filePath); VirtualFileTracker virtualFileTracker = ServiceManager.getService(VirtualFileTracker.class); MessageBus messageBus = (MessageBus)picoContainer.getComponentInstanceOfType(MessageBus.class); if (virtualFileTracker != null && messageBus != null) { - final String path = myFile.getAbsolutePath(); - final String fileUrl = LocalFileSystem.PROTOCOL_PREFIX + path.replace(File.separatorChar, '/'); - final Listener listener = messageBus.syncPublisher(STORAGE_TOPIC); - virtualFileTracker.addTracker(fileUrl, new VirtualFileAdapter() { + virtualFileTracker.addTracker(LocalFileSystem.PROTOCOL_PREFIX + myFile.getAbsolutePath().replace(File.separatorChar, '/'), new VirtualFileAdapter() { @Override public void fileMoved(@NotNull VirtualFileMoveEvent event) { myCachedVirtualFile = null; @@ -178,7 +173,7 @@ public class FileBasedStorage extends XmlElementStorage { @NotNull @Override - public Collection getStorageFilesToSave() { + public Collection getStorageFilesToSave() { if (needsSave()) { if (LOG.isDebugEnabled()) { LOG.info("File " + myFileSpec + " needs save; hash=" + myUpToDateHash + "; currentHash=" + calcHash() + "; " + @@ -193,7 +188,7 @@ public class FileBasedStorage extends XmlElementStorage { @NotNull @Override - public List getAllStorageFiles() { + public List getAllStorageFiles() { return Collections.singletonList(myFile); } } @@ -243,7 +238,7 @@ public class FileBasedStorage extends XmlElementStorage { } public File getFile() { - return new File(myFile.getPath()); + return myFile; } @Override @@ -324,7 +319,7 @@ public class FileBasedStorage extends XmlElementStorage { public File updateFileExternallyFromStreamProviders() throws IOException { Element element = getElement(loadData(true, null)); if (element == null) { - myFile.delete(); + FileUtil.delete(myFile); return null; } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java index 0427a8be15ab..93a65a2eb50b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java @@ -19,10 +19,10 @@ import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.StateStorageException; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.io.fs.IFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.io.IOException; import java.util.List; import java.util.Set; @@ -54,17 +54,19 @@ public interface IComponentStore { interface SaveSession { @NotNull - List getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException; + List getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException; + @NotNull SaveSession save() throws IOException; + void finishSave(); + void reset(); @Nullable - Set analyzeExternalChanges(@NotNull Set> changedFiles); + Set analyzeExternalChanges(@NotNull Set> changedFiles); @NotNull - List getAllStorageFiles(final boolean includingSubStructures); + List getAllStorageFiles(final boolean includingSubStructures); } - } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java index 66a6aec7ad21..e73814ed5a31 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java @@ -39,9 +39,8 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.*; +import com.intellij.util.SmartList; import com.intellij.util.containers.OrderedSet; -import com.intellij.util.io.fs.FileSystem; -import com.intellij.util.io.fs.IFile; import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NonNls; @@ -67,7 +66,6 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject protected ProjectImpl myProject; private StorageScheme myScheme = StorageScheme.DEFAULT; - private String myCachedLocation; private String myPresentableUrl; ProjectStoreImpl(final ProjectImpl project) { @@ -202,7 +200,6 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject }, ModalityState.defaultModalityState()); } - myCachedLocation = null; myPresentableUrl = null; } @@ -479,19 +476,16 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject @NotNull @Override - public List getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException { - List result = new ArrayList(); - + public List getAllStorageFilesToSave(final boolean includingSubStructures) throws IOException { + List result = new SmartList(); if (includingSubStructures) { - collectSubfilesToSave(result); + collectSubFilesToSave(result); } - result.addAll(super.getAllStorageFilesToSave(false)); - return result; } - protected void collectSubfilesToSave(final List result) throws IOException { } + protected void collectSubFilesToSave(final List result) throws IOException { } @NotNull @Override @@ -523,10 +517,10 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject return ApplicationManager.getApplication().runReadAction(new Computable() { @Override public ReadonlyStatusHandler.OperationStatus compute() { - final List filesToSave; + final List filesToSave; try { filesToSave = getAllStorageFilesToSave(true); - final Iterator iterator = filesToSave.iterator(); + final Iterator iterator = filesToSave.iterator(); while (iterator.hasNext()) { if (!iterator.next().exists()) { iterator.remove(); @@ -543,14 +537,12 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject if (myProject.isToSaveProjectName()) { final VirtualFile baseDir = getProjectBaseDir(); if (baseDir != null && baseDir.isValid()) { - filesToSave.add(FileSystem.FILE_SYSTEM - .createFile(new File(new File(baseDir.getPath(), Project.DIRECTORY_STORE_FOLDER), ProjectImpl.NAME_FILE).getPath())); + filesToSave.add(new File(new File(baseDir.getPath(), Project.DIRECTORY_STORE_FOLDER), ProjectImpl.NAME_FILE)); } } - for (IFile file : filesToSave) { + for (File file : filesToSave) { final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(file); - if (virtualFile != null) { virtualFile.refresh(false, false); if (virtualFile.isValid() && !virtualFile.isWritable()) { @@ -688,6 +680,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject return StateSplitter.class; } + @NotNull @Override public Class annotationType() { throw new UnsupportedOperationException("Method annotationType not implemented in " + getClass()); diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java index 92560821612b..79e079303281 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManager.java @@ -19,10 +19,10 @@ import com.intellij.openapi.components.*; import com.intellij.openapi.options.StreamProvider; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.io.fs.IFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.util.Collection; import java.util.List; import java.util.Set; @@ -82,11 +82,11 @@ public interface StateStorageManager { Set analyzeExternalChanges(@NotNull Set> files); @NotNull - List getAllStorageFilesToSave() throws StateStorageException; + List getAllStorageFilesToSave() throws StateStorageException; @NotNull - List getAllStorageFiles(); + List getAllStorageFiles(); void save() throws StateStorageException; } -} \ No newline at end of file +} diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java index a870112bd19b..4c935059cd39 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java @@ -24,12 +24,12 @@ import com.intellij.openapi.options.CurrentUserHolder; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ObjectUtils; import com.intellij.util.PathUtilRt; import com.intellij.util.SmartList; -import com.intellij.util.io.fs.IFile; import gnu.trove.THashMap; import gnu.trove.THashSet; import gnu.trove.TObjectLongHashMap; @@ -424,7 +424,8 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di @Override @Nullable public StateStorage getOldStorage(Object component, String componentName, StateStorageOperation operation) throws StateStorageException { - return getFileStateStorage(getOldStorageSpec(component, componentName, operation)); + String oldStorageSpec = getOldStorageSpec(component, componentName, operation); + return oldStorageSpec == null ? null : getFileStateStorage(oldStorageSpec); } @Nullable @@ -440,14 +441,14 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di @Override @NotNull - public List getAllStorageFilesToSave() throws StateStorageException { + public List getAllStorageFilesToSave() throws StateStorageException { assert mySession == this; return myCompoundSaveSession.getAllStorageFilesToSave(); } @Override @NotNull - public List getAllStorageFiles() { + public List getAllStorageFiles() { return myCompoundSaveSession.getAllStorageFiles(); } @@ -506,10 +507,7 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di if (!isDirty) return; String filePath = getNotNullVersionsFilePath(); if (filePath != null) { - File dir = new File(filePath).getParentFile(); - if (!dir.isDirectory() && !dir.mkdirs()) { - LOG.warn("Unable to create: " + dir); - } + FileUtilRt.createParentDirs(new File(filePath)); try { JDOMUtil.writeDocument(new Document(createComponentVersionsXml(getComponentVersions())), filePath, "\n"); isDirty = false; @@ -546,6 +544,7 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di return root; } + @SuppressWarnings("deprecation") private static class OldStreamProviderManager extends StreamProvider implements CurrentUserHolder { private final List myStreamProviders = new SmartList(); diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java index 477176dbb9fc..ba8029f5bef6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java @@ -37,7 +37,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.SystemProperties; import com.intellij.util.UniqueFileNamesProvider; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.io.fs.IFile; import com.intellij.util.ui.UIUtil; import org.jdom.Document; import org.jdom.Element; @@ -128,9 +127,9 @@ public class StorageUtil { * Due to historical reasons files in ROOT_CONFIG don’t wrapped into document (xml prolog) opposite to files in APP_CONFIG */ @Nullable - static VirtualFile save(@NotNull IFile file, @Nullable Parent element, Object requestor, boolean wrapAsDocument) throws StateStorageException { + static VirtualFile save(@NotNull File file, @Nullable Parent element, Object requestor, boolean wrapAsDocument) throws StateStorageException { if (isEmpty(element)) { - file.delete(); + FileUtil.delete(file); return null; } @@ -145,7 +144,7 @@ public class StorageUtil { } } else { - file.createParentDirs(); + FileUtil.createParentDirs(file); byteOut = writeToBytes(document, SystemProperties.getLineSeparator()); } @@ -179,28 +178,26 @@ public class StorageUtil { } @NotNull - static VirtualFile getOrCreateVirtualFile(final Object requestor, final IFile ioFile) throws IOException { - VirtualFile vFile = getVirtualFile(ioFile); - - if (vFile == null) { - vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile); + static VirtualFile getOrCreateVirtualFile(@Nullable Object requestor, @NotNull File ioFile) throws IOException { + VirtualFile virtualFile = getVirtualFile(ioFile); + if (virtualFile == null) { + virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile); } - if (vFile == null) { - final IFile parentFile = ioFile.getParentFile(); - final VirtualFile parentVFile = - LocalFileSystem.getInstance().refreshAndFindFileByIoFile(parentFile); // need refresh if the directory has just been created - if (parentVFile == null) { - throw new IOException(ProjectBundle.message("project.configuration.save.file.not.found", parentFile.getPath())); + if (virtualFile == null) { + File parentFile = ioFile.getParentFile(); + // need refresh if the directory has just been created + VirtualFile parentVirtualFile = parentFile == null ? null : LocalFileSystem.getInstance().refreshAndFindFileByIoFile(parentFile); + if (parentVirtualFile == null) { + throw new IOException(ProjectBundle.message("project.configuration.save.file.not.found", parentFile == null ? "" : parentFile.getPath())); } - vFile = parentVFile.createChildData(requestor, ioFile.getName()); + virtualFile = parentVirtualFile.createChildData(requestor, ioFile.getName()); } - - return vFile; + return virtualFile; } @Nullable - static VirtualFile getVirtualFile(final IFile ioFile) { + static VirtualFile getVirtualFile(@NotNull File ioFile) { return LocalFileSystem.getInstance().findFileByIoFile(ioFile); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java index ccb0b6fc08ed..c75e99dc1806 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java @@ -26,7 +26,6 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.vfs.SafeWriteRequestor; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.io.fs.IFile; import gnu.trove.THashMap; import gnu.trove.THashSet; import gnu.trove.TObjectLongHashMap; @@ -37,12 +36,13 @@ import org.jdom.filter.ElementFilter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.*; public abstract class XmlElementStorage implements StateStorage, Disposable { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.XmlElementStorage"); + private static final Logger LOG = Logger.getInstance(XmlElementStorage.class); private static final String ATTR_NAME = "name"; private static final String VERSION_FILE_SUFFIX = ".ver"; @@ -235,13 +235,13 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { @NotNull @Override - public Collection getStorageFilesToSave() throws StateStorageException { + public Collection getStorageFilesToSave() throws StateStorageException { return Collections.emptySet(); } @NotNull @Override - public List getAllStorageFiles() { + public List getAllStorageFiles() { return Collections.emptyList(); } }; diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java index d2ea19bc403d..2938f419909c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java @@ -122,6 +122,9 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD if (toSelect.length == 1) { restoreSelection(toSelect[0]); } + else if (toSelect.length == 0) { + restoreSelection(null); // select last opened file + } else { selectInTree(toSelect, true); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java index 30eb78cf706f..c074a4965493 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorManagerEx.java @@ -164,6 +164,7 @@ public abstract class FileEditorManagerEx extends FileEditorManager implements B public abstract boolean isInsideChange(); + @Override @Nullable public final Object getData(@NotNull String dataId, @NotNull Editor editor, @NotNull Caret caret) { for (final EditorDataProvider dataProvider : myDataProviders) { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java index 48a5b7c9a4dc..d8a704d891bf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.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. @@ -66,7 +66,7 @@ public abstract class EditorComposite implements Disposable { /** * File for which composite is created */ - private final VirtualFile myFile; + @NotNull private final VirtualFile myFile; /** * Whether the composite is pinned or not */ diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java index 32169662ba2a..ddd5395805ff 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorHistoryManager.java @@ -287,7 +287,7 @@ public final class EditorHistoryManager extends AbstractProjectComponent impleme } } - public FileEditorState getState(final VirtualFile file, final FileEditorProvider provider) { + public FileEditorState getState(@NotNull VirtualFile file, final FileEditorProvider provider) { validateEntries(); final HistoryEntry entry = getEntry(file); return entry != null ? entry.getState(provider) : null; @@ -302,7 +302,7 @@ public final class EditorHistoryManager extends AbstractProjectComponent impleme return entry != null ? entry.mySelectedProvider : null; } - private HistoryEntry getEntry(final VirtualFile file){ + private HistoryEntry getEntry(@NotNull VirtualFile file){ validateEntries(); for (int i = myEntriesList.size() - 1; i >= 0; i--) { final HistoryEntry entry = myEntriesList.get(i); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabColorProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabColorProvider.java index babf76dd3709..58f5470aca07 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabColorProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabColorProvider.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. @@ -18,6 +18,7 @@ package com.intellij.openapi.fileEditor.impl; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.extensions.ExtensionPointName; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; @@ -29,5 +30,5 @@ public interface EditorTabColorProvider { ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.editorTabColorProvider"); @Nullable - Color getEditorTabColor(Project project, VirtualFile file); + Color getEditorTabColor(@NotNull Project project, @NotNull VirtualFile file); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java index 03b03faffe03..3fa0f751e9cb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.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. @@ -381,7 +381,7 @@ public final class EditorTabbedContainer implements Disposable, CloseAction.Clos } @Nullable - public static Color calcTabColor(final Project project, final VirtualFile file) { + public static Color calcTabColor(@NotNull Project project, @NotNull VirtualFile file) { for (EditorTabColorProvider provider : Extensions.getExtensions(EditorTabColorProvider.EP_NAME)) { final Color result = provider.getEditorTabColor(project, file); if (result != null) { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java index 06a3966ade1d..1bf86ea5d62c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java @@ -287,7 +287,7 @@ public class EditorWindow { } } - public void closeFile(final VirtualFile file, final boolean disposeIfNeeded, final boolean transferFocus) { + public void closeFile(@NotNull final VirtualFile file, final boolean disposeIfNeeded, final boolean transferFocus) { final FileEditorManagerImpl editorManager = getManager(); editorManager.runChange(new FileEditorManagerChange() { @Override @@ -525,7 +525,7 @@ public class EditorWindow { myOwner.setCurrentWindow(this, requestFocus); } - public void updateFileBackgroundColor(final VirtualFile file) { + public void updateFileBackgroundColor(@NotNull VirtualFile file) { final int index = findEditorIndex(findFileComposite(file)); if (index != -1) { final Color color = EditorTabbedContainer.calcTabColor(getManager().getProject(), file); @@ -569,10 +569,10 @@ public class EditorWindow { } protected static class TComp extends JPanel implements DataProvider, EditorWindowHolder { - final EditorWithProviderComposite myEditor; + @NotNull final EditorWithProviderComposite myEditor; protected final EditorWindow myWindow; - TComp(final EditorWindow window, final EditorWithProviderComposite editor) { + TComp(@NotNull EditorWindow window, @NotNull EditorWithProviderComposite editor) { super(new BorderLayout()); myEditor = editor; myWindow = window; @@ -594,6 +594,7 @@ public class EditorWindow { }); } + @NotNull @Override public EditorWindow getEditorWindow() { return myWindow; @@ -613,7 +614,7 @@ public class EditorWindow { } protected static class TCompForTablessMode extends TComp implements CloseAction.CloseTarget { - TCompForTablessMode(final EditorWindow window, final EditorWithProviderComposite editor) { + TCompForTablessMode(@NotNull EditorWindow window, @NotNull EditorWithProviderComposite editor) { super(window, editor); } @@ -701,6 +702,7 @@ public class EditorWindow { public void setEditor(@Nullable final EditorWithProviderComposite editor, final boolean selectEditor, final boolean focusEditor) { if (editor != null) { + onBeforeSetEditor(editor.getFile()); if (myTabbedPane == null) { myPanel.removeAll (); myPanel.add (new TCompForTablessMode(this, editor), BorderLayout.CENTER); @@ -741,6 +743,9 @@ public class EditorWindow { myOwner.validate(); } + protected void onBeforeSetEditor(VirtualFile file) { + } + private boolean splitAvailable() { return getTabCount() >= 1; } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java index c708d058b63b..2d27bb853531 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindowHolder.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. @@ -15,9 +15,12 @@ */ package com.intellij.openapi.fileEditor.impl; +import org.jetbrains.annotations.NotNull; + /** * @author Konstantin Bulenkov */ public interface EditorWindowHolder { + @NotNull EditorWindow getEditorWindow(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java index fa0a4dbd6fe4..f7ba3b99156d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java @@ -463,7 +463,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener myCurrentWindow = currentWindow; } - public void updateFileBackgroundColor(final VirtualFile file) { + public void updateFileBackgroundColor(@NotNull VirtualFile file) { final EditorWindow[] windows = getWindows(); for (int i = 0; i != windows.length; ++ i) { windows [i].updateFileBackgroundColor(file); @@ -614,10 +614,14 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener public void createCurrentWindow() { LOG.assertTrue(myCurrentWindow == null); - setCurrentWindow(new EditorWindow(this)); + setCurrentWindow(createEditorWindow()); add(myCurrentWindow.myPanel, BorderLayout.CENTER); } + protected EditorWindow createEditorWindow() { + return new EditorWindow(this); + } + /** * sets the window passed as a current ('focused') window among all splitters. All file openings will be done inside this * current window @@ -625,7 +629,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener * @param requestFocus whether to request focus to the editor currently selected in this window */ public void setCurrentWindow(@Nullable final EditorWindow window, final boolean requestFocus) { - final EditorWithProviderComposite newEditor = window != null? window.getSelectedEditor() : null; + final EditorWithProviderComposite newEditor = window == null ? null : window.getSelectedEditor(); Runnable fireRunnable = new Runnable() { @Override @@ -655,7 +659,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener //--------------------------------------------------------- public EditorWithProviderComposite[] getEditorsComposites() { - final ArrayList res = new ArrayList(); + List res = new ArrayList(); for (final EditorWindow myWindow : myWindows) { final EditorWithProviderComposite[] editors = myWindow.getEditors(); @@ -667,8 +671,8 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener //--------------------------------------------------------- @NotNull - public List findEditorComposites(final VirtualFile file) { - final ArrayList res = new ArrayList(); + public List findEditorComposites(@NotNull VirtualFile file) { + List res = new ArrayList(); for (final EditorWindow window : myWindows) { final EditorWithProviderComposite fileComposite = window.findFileComposite(file); if (fileComposite != null) { @@ -680,7 +684,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener @NotNull public List findWindows(final VirtualFile file) { - final ArrayList res = new ArrayList(); + List res = new ArrayList(); for (final EditorWindow window : myWindows) { if (window.findFileComposite(file) != null) { res.add(window); @@ -694,7 +698,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener } @NotNull public EditorWindow[] getOrderedWindows() { - final ArrayList res = new ArrayList(); + final List res = new ArrayList(); // Collector for windows in tree ordering: class Inner{ @@ -832,7 +836,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener UIUtil.invokeAndWaitIfNeeded(new Runnable() { @Override public void run() { - windowRef.set(context == null ? new EditorWindow(EditorsSplitters.this) : findWindowWith(context)); + windowRef.set(context == null ? createEditorWindow() : findWindowWith(context)); } }); final EditorWindow window = windowRef.get(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index 1cedbd8c3c00..483571f786cb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -58,7 +58,6 @@ import com.intellij.openapi.vcs.FileStatusListener; import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.*; 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.ex.StatusBarEx; @@ -91,7 +90,6 @@ import java.beans.PropertyChangeListener; import java.lang.ref.WeakReference; import java.util.*; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; /** * @author Anton Katilin @@ -113,7 +111,6 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec private final Project myProject; private final List> mySelectionHistory = new ArrayList>(); private WeakReference myLastSelectedComposite = new WeakReference(null); - private final AtomicBoolean myPreviewBlocker = new AtomicBoolean(false); private final MergingUpdateQueue myQueue = new MergingUpdateQueue("FileEditorManagerUpdateQueue", 50, true, null); @@ -181,8 +178,9 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec HashSet all = new LinkedHashSet(); if (PreviewPanel.isAvailable()) { initUI(); - if (!myProject.isDisposed()) { - all.add(myPreviewPanel.getWindow().getOwner()); + EditorWindow window = myPreviewPanel.getWindow(); + if (window != null) { + all.add(window.getOwner()); } } all.add(getMainSplitters()); @@ -266,7 +264,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec private static class MyBorder implements Border { @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + public void paintBorder(@NotNull Component c, @NotNull Graphics g, int x, int y, int width, int height) { if (UIUtil.isUnderAquaLookAndFeel()) { g.setColor(JBTabsImpl.MAC_AQUA_BG_COLOR); final Insets insets = getBorderInsets(c); @@ -276,6 +274,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec } } + @NotNull @Override public Insets getBorderInsets(Component c) { return JBInsets.NONE; @@ -644,7 +643,8 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec } if (wndToOpenIn == null || !wndToOpenIn.isFileOpen(file)) { - EditorWindow previewWindow = getPreviewWindow(file, focusEditor, searchForSplitter); + initUI(); + EditorWindow previewWindow = PreviewPanel.isAvailable() && myPreviewPanel != null ? myPreviewPanel.getWindow() : null; if (previewWindow != null) { wndToOpenIn = previewWindow; } @@ -660,31 +660,6 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec return openFileImpl2(wndToOpenIn, file, focusEditor); } - @Nullable - private EditorWindow getPreviewWindow(@NotNull VirtualFile virtualFile, final boolean focusEditor, final boolean searchForSplitter) { - EditorWindow wndToOpenIn = null; - if (PreviewPanel.isAvailable() && !myPreviewBlocker.get()) { - wndToOpenIn = myPreviewPanel.getWindow(); - if (myPreviewPanel.hasCurrentFile(virtualFile)) return wndToOpenIn; - final VirtualFile modifiedFile = myPreviewPanel.getCurrentModifiedFile(); - ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW).activate(null, false); - if (modifiedFile != null) { - CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { - @Override - public void run() { - myPreviewBlocker.set(true); - try { - openFileWithProviders(modifiedFile, focusEditor, searchForSplitter); - } finally { - myPreviewBlocker.set(false); - } - } - }, "", null); - } - } - return wndToOpenIn; - } - public Pair openFileInNewWindow(@NotNull VirtualFile file) { return ((DockManagerImpl)DockManager.getInstance(getProject())).createNewDockContainerFor(file, this); } @@ -807,7 +782,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec final FileEditorProvider provider = newProviders[i]; LOG.assertTrue(provider != null, "Provider for file "+file+" is null. All providers: "+Arrays.asList(newProviders)); LOG.assertTrue(provider.accept(myProject, file), "Provider " + provider + " doesn't accept file " + file); - if ((provider instanceof AsyncFileEditorProvider)) { + if (provider instanceof AsyncFileEditorProvider) { builders[i] = ((AsyncFileEditorProvider)provider).createEditorAsync(myProject, file); } } @@ -946,7 +921,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec return Pair.create(compositeRef.get().getEditors(), compositeRef.get().getProviders()); } - private void clearWindowIfNeeded(EditorWindow window) { + private static void clearWindowIfNeeded(EditorWindow window) { if (UISettings.getInstance().EDITOR_TAB_PLACEMENT == UISettings.TABS_NONE || UISettings.getInstance().PRESENTATION_MODE) { for (EditorWithProviderComposite composite : window.getEditors()) { Disposer.dispose(composite); @@ -1179,9 +1154,13 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec @Override public Editor getSelectedTextEditor() { - assertReadAccess(); + return getSelectedTextEditor(false); + } - final EditorWindow currentWindow = getSplitters().getCurrentWindow(); + public Editor getSelectedTextEditor(boolean lockfree) { + assertDispatchThread(); + + final EditorWindow currentWindow = lockfree ? getMainSplitters().getCurrentWindow() : getSplitters().getCurrentWindow(); if (currentWindow != null) { final EditorWithProviderComposite selectedEditor = currentWindow.getSelectedEditor(); if (selectedEditor != null && selectedEditor.getSelectedEditor() instanceof TextEditor) { @@ -1193,6 +1172,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec } + @Override public boolean isFileOpen(@NotNull final VirtualFile file) { return !getEditorComposites(file).isEmpty(); @@ -1762,7 +1742,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec private final class MyEditorPropertyChangeListener implements PropertyChangeListener { @Override - public void propertyChange(final PropertyChangeEvent e) { + public void propertyChange(@NotNull final PropertyChangeEvent e) { assertDispatchThread(); final String propertyName = e.getPropertyName(); @@ -2001,6 +1981,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec mySelectionHistory.remove(Pair.create(file, window)); } + @NotNull @Override public ActionCallback getReady(@NotNull Object requestor) { return myBusyObject.getReady(requestor); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java index 752ab1228c3e..0e4f057dbeaf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/IdeDocumentHistoryImpl.java @@ -145,16 +145,12 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec } public static class RecentlyChangedFilesState { - @Transient private List CHANGED_PATHS = new ArrayList(); + @Transient private final List CHANGED_PATHS = new ArrayList(); public List getChangedFiles() { return CHANGED_PATHS; } - public void setChangedFiles(List changed) { - CHANGED_PATHS = changed; - } - public void register(VirtualFile file) { final String path = file.getPath(); CHANGED_PATHS.remove(path); @@ -275,7 +271,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec myCurrentChangePlace = placeInfo; if (!myChangePlaces.isEmpty()) { - final PlaceInfo lastInfo = myChangePlaces.get(myChangePlaces.size() - 1); + final PlaceInfo lastInfo = myChangePlaces.getLast(); if (isSame(placeInfo, lastInfo)) { myChangePlaces.removeLast(); } @@ -430,7 +426,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec } } - private static boolean removeInvalidFilesFrom(final LinkedList backPlaces) { + private static boolean removeInvalidFilesFrom(@NotNull List backPlaces) { boolean removed = false; for (Iterator iterator = backPlaces.iterator(); iterator.hasNext();) { PlaceInfo info = iterator.next(); @@ -456,7 +452,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec myEditorManager.setSelectedEditor(info.getFile(), info.getEditorTypeId()); - final FileEditor [] editors = editorsWithProviders.getFirst(); + final FileEditor[] editors = editorsWithProviders.getFirst(); final FileEditorProvider[] providers = editorsWithProviders.getSecond(); for (int i = 0; i < editors.length; i++) { String typeId = providers [i].getEditorTypeId(); @@ -483,7 +479,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec return new PlaceInfo(file, state, fileProvider.getEditorTypeId(), myEditorManager.getCurrentWindow()); } - private static void clearPlaceList(LinkedList list) { + private static void clearPlaceList(@NotNull List list) { list.clear(); } @@ -494,9 +490,9 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec return "IdeDocumentHistory"; } - private static void putLastOrMerge(LinkedList list, PlaceInfo next, int limitSizeLimit) { + private static void putLastOrMerge(@NotNull LinkedList list, @NotNull PlaceInfo next, int limitSizeLimit) { if (!list.isEmpty()) { - PlaceInfo prev = list.get(list.size() - 1); + PlaceInfo prev = list.getLast(); if (isSame(prev, next)) { list.removeLast(); } @@ -522,7 +518,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec private final String myEditorTypeId; private final WeakReference myWindow; - public PlaceInfo(@NotNull VirtualFile file, FileEditorState navigationState, String editorTypeId, @Nullable EditorWindow window) { + public PlaceInfo(@NotNull VirtualFile file, @NotNull FileEditorState navigationState, @NotNull String editorTypeId, @Nullable EditorWindow window) { myNavigationState = navigationState; myFile = file; myEditorTypeId = editorTypeId; @@ -533,6 +529,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec return myWindow.get(); } + @NotNull public FileEditorState getNavigationState() { return myNavigationState; } @@ -542,24 +539,23 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec return myFile; } + @NotNull public String getEditorTypeId() { return myEditorTypeId; } + @Override public String toString() { return getFile().getName() + " " + getNavigationState(); } } - public LinkedList getBackPlaces() { + @NotNull + public List getBackPlaces() { return myBackPlaces; } - public LinkedList getForwardPlaces() { - return myForwardPlaces; - } - @Override public final void initComponent() { } @@ -572,7 +568,7 @@ public class IdeDocumentHistoryImpl extends IdeDocumentHistory implements Projec myCmdProcessor.executeCommand(myProject, runnable, name, groupId); } - private static boolean isSame(PlaceInfo first, PlaceInfo second) { + private static boolean isSame(@NotNull PlaceInfo first, @NotNull PlaceInfo second) { if (first.getFile().equals(second.getFile())) { FileEditorState firstState = first.getNavigationState(); FileEditorState secondState = second.getNavigationState(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java index ade7001fc279..1c9af86cd12a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/PreviewPanel.java @@ -17,8 +17,11 @@ package com.intellij.openapi.fileEditor.impl; import com.intellij.icons.AllIcons; import com.intellij.ide.ui.UISettings; +import com.intellij.ide.ui.UISettingsListener; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.actionSystem.ToggleAction; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.FileEditorManagerListener; @@ -41,8 +44,11 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.util.ArrayList; +import java.util.EnumSet; class PreviewPanel extends JPanel { + enum ContentType {Files, Usages, Diagrams, Documentation} + private static final Key FILE_KEY = Key.create("v_file"); private static final int HISTORY_LIMIT = 10; @@ -57,6 +63,9 @@ class PreviewPanel extends JPanel { private VirtualFile myAwaitingForOpen = null; private ContentManager myContentManager; private Content myStubContent; + private boolean myBlocked = false; + + private EnumSet myTypes = EnumSet.noneOf(ContentType.class); static boolean isAvailable() { return UISettings.getInstance().NAVIGATE_TO_PREVIEW; @@ -68,28 +77,37 @@ class PreviewPanel extends JPanel { myDockManager = dockManager; } - // package-private API - + /* + * @return null if preview is not avalable + */ + @Nullable EditorWindow getWindow() { + if (!isAvailable() || isBlocked() || myProject.isDisposed()) return null; initToolWindowIfNeed(); return myWindow; } - boolean hasCurrentFile(@NotNull VirtualFile file) { - return file.equals(getCurrentFile()); - } - - @Nullable - VirtualFile getCurrentModifiedFile() { - VirtualFile file = getCurrentFile(); - return file != null && file.equals(myModifiedFile) ? file : null; + boolean isBlocked() { + return myBlocked; } private void initToolWindowIfNeed() { - if (ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW) != null) return; + if (!isAvailable() || ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW) != null) return; myToolWindow = (ToolWindowImpl)ToolWindowManager.getInstance(myProject) .registerToolWindow(ToolWindowId.PREVIEW, this, ToolWindowAnchor.RIGHT, myProject, false); + UISettings.getInstance().addUISettingsListener(new UISettingsListener() { + @Override + public void uiSettingsChanged(UISettings source) { + if (!isAvailable()) { + VirtualFile[] files = myWindow.getFiles(); + for (VirtualFile file : files) { + close(file); + } + ToolWindowManager.getInstance(myProject).unregisterToolWindow(ToolWindowId.PREVIEW); + } + } + }, myProject); myToolWindow.setIcon(AllIcons.Actions.PreviewDetails); myToolWindow.setContentUiType(ToolWindowContentUiType.COMBO, null); myContentManager = myToolWindow.getContentManager(); @@ -147,6 +165,11 @@ class PreviewPanel extends JPanel { setLayout(new GridLayout(1, 1)); add(myEditorsSplitters); myToolWindow.setTitleActions(new MoveToEditorTabsAction(), new CloseFileAction()); + ArrayList myGearActions = new ArrayList(); + for (ContentType contentType : ContentType.values()) { + myGearActions.add(new ContentTypeToggleAction(contentType)); + } + myToolWindow.setAdditionalGearActions(new DefaultActionGroup("Preview", myGearActions)); myToolWindow.hide(null); } @@ -204,7 +227,7 @@ class PreviewPanel extends JPanel { @Override public void run() { if (myContentManager.getIndexOfContent(myStubContent) != -1) { - ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW).hide(null); + toggleToolWindow(false); } } }); @@ -224,6 +247,13 @@ class PreviewPanel extends JPanel { myAwaitingForOpen = null; } if (file.equals(myModifiedFile)) { + myBlocked = true; + try { + myManager.openFileWithProviders(myModifiedFile, false, true); + } + finally { + myBlocked = false; + } myModifiedFile = null; } Content content = getContent(file); @@ -233,9 +263,22 @@ class PreviewPanel extends JPanel { } } + private void toggleToolWindow(boolean activate) { + ToolWindow toolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW); + if (toolWindow != null) { + if (activate) { + toolWindow.activate(null, false); + } + else { + toolWindow.hide(null); + } + } + } + private class MoveToEditorTabsAction extends AnAction { + public MoveToEditorTabsAction() { - super(null, "Move to main tabs", AllIcons.Duplicates.SendToTheLeftGrayed); + super("Move to main tabs", "Move to main tabs", AllIcons.Duplicates.SendToTheLeftGrayed); } @Override @@ -252,14 +295,14 @@ class PreviewPanel extends JPanel { } myManager.openFileWithProviders(virtualFile, true, window); close(virtualFile); - ToolWindowManager.getInstance(myProject).getToolWindow(ToolWindowId.PREVIEW).hide(null); + toggleToolWindow(false); } } private class CloseFileAction extends AnAction { public CloseFileAction() { - super(null, "Close", AllIcons.Actions.Close); + super("Close", "Close", AllIcons.Actions.Close); } @Override @@ -267,6 +310,30 @@ class PreviewPanel extends JPanel { for (VirtualFile file : myHistory.toArray(new VirtualFile[myHistory.size()])) { close(file); } + toggleToolWindow(false); + } + } + + private class ContentTypeToggleAction extends ToggleAction { + private final ContentType myContentType; + + ContentTypeToggleAction(ContentType contentType) { + super(contentType.toString()); + myContentType = contentType; + } + + @Override + public boolean isSelected(AnActionEvent e) { + return myTypes.contains(myContentType); + } + + @Override + public void setSelected(AnActionEvent e, boolean state) { + if (state) { + myTypes.add(myContentType); + } else { + myTypes.remove(myContentType); + } } } @@ -296,6 +363,28 @@ class PreviewPanel extends JPanel { } } + @Override + protected EditorWindow createEditorWindow() { + return new EditorWindow(this) { + @Override + protected void onBeforeSetEditor(VirtualFile file) { + VirtualFile currentFile = getCurrentFile(); + if (currentFile != null && currentFile.equals(myModifiedFile)) { + myBlocked = true; + try { + myManager.openFileWithProviders(myModifiedFile, false, true); + } + finally { + myBlocked = false; + } + } + else { + toggleToolWindow(true); + } + } + }; + } + @Override public void setTabsPlacement(int tabPlacement) { super.setTabsPlacement(UISettings.TABS_NONE); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java index 429a55b2b809..ca72bf30c541 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java @@ -48,7 +48,7 @@ public class ConfigurableExtensionPointUtil { } } - final Map idToConfigurable = new HashMap(); + final Map idToConfigurable = new LinkedHashMap(); for (ConfigurableEP ep : extensions) { final Configurable configurable = ConfigurableWrapper.wrapConfigurable(ep); if (isSuppressed(configurable, filter)) continue; @@ -75,16 +75,13 @@ public class ConfigurableExtensionPointUtil { } } } - //leave only roots (i.e. configurables without parents) - for (final Iterator iterator = idToConfigurable.keySet().iterator(); iterator.hasNext(); ) { - final String key = iterator.next(); - final ConfigurableWrapper wrapper = idToConfigurable.get(key); - final String parentId = wrapper.getParentId(); - if (parentId != null && idToConfigurable.containsKey(parentId)) { - iterator.remove(); // remove only processed parents + // add roots only (i.e. configurables without parents) + for (ConfigurableWrapper wrapper : idToConfigurable.values()) { + String parentId = wrapper.getParentId(); + if (parentId == null || !idToConfigurable.containsKey(parentId)) { + result.add(wrapper); } } - ContainerUtil.addAll(result, idToConfigurable.values()); return result; } @@ -164,7 +161,7 @@ public class ConfigurableExtensionPointUtil { @NotNull private static T findConfigurable(ConfigurableEP[] extensions, Class configurableClass) { for (ConfigurableEP extension : extensions) { - if (extension.providerClass != null || extension.instanceClass != null || extension.implementationClass != null) { + if (extension.canCreateConfigurable()) { final Configurable configurable = extension.createConfigurable(); if (configurableClass.isInstance(configurable)) { return configurableClass.cast(configurable); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java index b5a62f8ae395..83960e742ed1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java @@ -47,6 +47,9 @@ public class ConfigurableWrapper implements SearchableConfigurable { @Nullable public static T wrapConfigurable(ConfigurableEP ep) { + if (!ep.canCreateConfigurable()) { + return null; + } if (ep.displayName != null || ep.key != null || ep.groupId != null) { T configurable = null; if (ep.providerClass != null) { @@ -196,7 +199,7 @@ public class ConfigurableWrapper implements SearchableConfigurable { return configurable instanceof SearchableConfigurable ? ((SearchableConfigurable)configurable).enableSearch(option) : null; } - private static class CompositeWrapper extends ConfigurableWrapper implements SearchableConfigurable.Parent { + private static class CompositeWrapper extends ConfigurableWrapper implements Configurable.Composite { private Configurable[] myKids; @@ -241,42 +244,6 @@ public class ConfigurableWrapper implements SearchableConfigurable { myKids = ArrayUtil.append(myKids, configurable); return this; } - - @Override - public boolean hasOwnContent() { - UnnamedConfigurable configurable = getConfigurable(); - if (configurable instanceof SearchableConfigurable.Parent) { - SearchableConfigurable.Parent parent = (SearchableConfigurable.Parent)configurable; - return parent.hasOwnContent(); - } - return false; - } - - @Override - public boolean isVisible() { - if (super.myConfigurable == null) { - String name = super.myEp.instanceClass; - if (name == null) { - name = super.myEp.implementationClass; - } - if (name != null) { - try { - if (!SearchableConfigurable.Parent.class.isAssignableFrom(super.myEp.findClass(name))) { - return true; // do not instantiate wrapped configurable if not needed - } - } - catch (ClassNotFoundException exception) { - return true; // ignore unexpected exception from findClass - } - } - } - UnnamedConfigurable configurable = getConfigurable(); - if (configurable instanceof SearchableConfigurable.Parent) { - SearchableConfigurable.Parent parent = (SearchableConfigurable.Parent)configurable; - return parent.isVisible(); - } - return true; - } } private static final class GroupWrapper extends CompositeWrapper implements ConfigurableGroup { diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java index ee12807ed9e1..bf81c7b17cbe 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/MixedConfigurableGroup.java @@ -97,12 +97,6 @@ public final class MixedConfigurableGroup implements SearchableConfigurable, Con ArrayList groups = new ArrayList(); HashMap> map = new HashMap>(); for (Configurable configurable : configurables) { - if (configurable instanceof SearchableConfigurable.Parent) { - SearchableConfigurable.Parent parent = (SearchableConfigurable.Parent)configurable; - if (!parent.isVisible()) { - continue; - } - } if (configurable instanceof ConfigurableGroup) { groups.add((ConfigurableGroup)configurable); } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index e7b20959369e..b5243e7c7ec9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -57,7 +57,6 @@ import com.intellij.util.ArrayUtil; import com.intellij.util.TimeoutUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; -import com.intellij.util.io.fs.IFile; import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.UIUtil; @@ -922,9 +921,9 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt IProjectStore projectStore = projectImpl.getStateStore(); final String location = projectImpl.getPresentableUrl(); - final List original; + final List original; try { - final IComponentStore.SaveSession saveSession = projectStore.startSave(); + IComponentStore.SaveSession saveSession = projectStore.startSave(); original = saveSession.getAllStorageFiles(true); saveSession.finishSave(); } @@ -937,7 +936,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt application.runWriteAction(new Runnable() { @Override public void run() { - for (final IFile originalFile : original) { + for (File originalFile : original) { restoreCopy(LocalFileSystem.getInstance().refreshAndFindFileByIoFile(originalFile)); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java index e6c84f5e7768..17acd7d1ee66 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java @@ -28,6 +28,7 @@ import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.*; import com.intellij.ui.Gray; import com.intellij.ui.JBColor; @@ -447,6 +448,10 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa } } } + String separatorText = group.getTemplatePresentation().getText(); + if (children.length > 0 && !StringUtil.isEmpty(separatorText)) { + main.addAction(new Separator(separatorText), Constraints.FIRST); + } } /** diff --git a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java index ee586418dbd6..37646a19292f 100644 --- a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.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. @@ -94,6 +94,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo myProject = project; } + @Override public void register(final DockContainer container) { myContainers.add(container); Disposer.register(container, new Disposable() { @@ -147,6 +148,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo return wnd != null ? key + "#" + wnd.myId : key; } + @Override public DockContainer getContainerFor(Component c) { if (c == null) return null; @@ -401,7 +403,8 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo }); } - public Pair createNewDockContainerFor(@NotNull VirtualFile file, FileEditorManagerImpl fileEditorManager) { + @NotNull + public Pair createNewDockContainerFor(@NotNull VirtualFile file, @NotNull FileEditorManagerImpl fileEditorManager) { DockContainer container = getFactory(DockableEditorContainerFactory.TYPE).createContainer(null); register(container); diff --git a/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java b/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java index 2a70b61c6e8a..47ebb829adc2 100644 --- a/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java +++ b/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java @@ -190,7 +190,7 @@ public class JBMacMessages extends MacMessagesEmulation { SheetMessage sheetMessage = new SheetMessage(window, title, message, UIUtil.getQuestionIcon(), new String [] {yesButton, noButton}, doNotAskDialogOption, yesButton, noButton); int result = sheetMessage.getResult().equals(yesButton) ? Messages.YES : Messages.NO; - if (doNotAskDialogOption != null) { + if (doNotAskDialogOption != null && (result == Messages.YES || doNotAskDialogOption.shouldSaveOptionsOnCancel())) { doNotAskDialogOption.setToBeShown(sheetMessage.toBeShown(), result); } return result; diff --git a/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java index 1b9190f6a740..d8b512367f26 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java @@ -189,7 +189,7 @@ public abstract class WizardPopup extends AbstractPopup implements ActionListene targetBounds.x = getParent().getBounds().x - targetBounds.width - STEP_X_PADDING; } } else { - ScreenUtil.moveToFit(targetBounds, ScreenUtil.getScreenRectangle(aScreenX, aScreenY), null); + ScreenUtil.moveToFit(targetBounds, ScreenUtil.getScreenRectangle(aScreenX + 1, aScreenY + 1), null); } if (getParent() == null) { diff --git a/platform/platform-resources/src/META-INF/VcsExtensions.xml b/platform/platform-resources/src/META-INF/VcsExtensions.xml index 9aa86cfb9a01..8c416e6df410 100644 --- a/platform/platform-resources/src/META-INF/VcsExtensions.xml +++ b/platform/platform-resources/src/META-INF/VcsExtensions.xml @@ -25,7 +25,8 @@ - + diff --git a/platform/platform-resources/src/META-INF/xdebugger.xml b/platform/platform-resources/src/META-INF/xdebugger.xml index d28921d17ba6..821cb528b6a9 100644 --- a/platform/platform-resources/src/META-INF/xdebugger.xml +++ b/platform/platform-resources/src/META-INF/xdebugger.xml @@ -30,7 +30,8 @@ - + diff --git a/platform/platform-resources/src/launcher.py b/platform/platform-resources/src/launcher.py index 0a679eec98fe..f04a26cb2c83 100644 --- a/platform/platform-resources/src/launcher.py +++ b/platform/platform-resources/src/launcher.py @@ -18,10 +18,13 @@ for i, arg in enumerate(sys.argv[1:]): print(('Usage:\n' + \ ' {0} -h |-? | --help\n' + \ ' {0} [-l|--line line] file[:line]\n' + \ - ' {0} diff file1 file2').format(sys.argv[0])) + ' {0} diff \n' + \ + ' {0} merge [base] ').format(sys.argv[0])) exit(0) elif arg == 'diff' and i == 0: args.append(arg) + elif arg == 'merge' and i == 0: + args.append(arg) elif arg == '-l' or arg == '--line': args.append(arg) skip_next = True @@ -96,4 +99,4 @@ else: # unix common bin_dir, bin_file = os.path.split(RUN_PATH) os.chdir(bin_dir) - os.execv(bin_file, [bin_file] + args) + os.execv(bin_file, [bin_file] + args) \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java index 5900b67db6bd..e5b586022ec4 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/XmlElementStorageTest.java @@ -24,11 +24,11 @@ import com.intellij.openapi.components.impl.stores.ComponentVersionProvider; import com.intellij.openapi.components.impl.stores.XmlElementStorage; import com.intellij.openapi.util.Disposer; import com.intellij.testFramework.LightPlatformLangTestCase; -import com.intellij.util.io.fs.IFile; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -108,16 +108,15 @@ public class XmlElementStorageTest extends LightPlatformLangTestCase { @NotNull @Override - public Collection getStorageFilesToSave() throws StateStorageException { - return needsSave() ? getAllStorageFiles() : Collections.emptyList(); + public Collection getStorageFilesToSave() throws StateStorageException { + return needsSave() ? getAllStorageFiles() : Collections.emptyList(); } @NotNull @Override - public List getAllStorageFiles() { + public List getAllStorageFiles() { throw new UnsupportedOperationException("Method getAllStorageFiles not implemented in " + getClass()); } - }; } } diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/StateStorage.java b/platform/projectModel-api/src/com/intellij/openapi/components/StateStorage.java index 134821d7e326..e6c51699806f 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/StateStorage.java +++ b/platform/projectModel-api/src/com/intellij/openapi/components/StateStorage.java @@ -19,11 +19,11 @@ package com.intellij.openapi.components; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileEvent; -import com.intellij.util.io.fs.IFile; import com.intellij.util.messages.Topic; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.util.Collection; import java.util.List; import java.util.Set; @@ -57,10 +57,10 @@ public interface StateStorage { Set analyzeExternalChanges(@NotNull Set> changedFiles); @NotNull - Collection getStorageFilesToSave() throws StateStorageException; + Collection getStorageFilesToSave() throws StateStorageException; @NotNull - List getAllStorageFiles(); + List getAllStorageFiles(); } interface Listener { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DirectoryStorageData.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DirectoryStorageData.java index 6cb899798949..8ea0e1ef935f 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DirectoryStorageData.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/stores/DirectoryStorageData.java @@ -23,8 +23,6 @@ import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.PairConsumer; -import com.intellij.util.io.fs.FileSystem; -import com.intellij.util.io.fs.IFile; import gnu.trove.THashMap; import org.jdom.Document; import org.jdom.Element; @@ -37,9 +35,9 @@ import java.io.IOException; import java.util.*; public class DirectoryStorageData { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.DirectoryStorageData"); + private static final Logger LOG = Logger.getInstance(DirectoryStorageData.class); - private Map> myStates = new HashMap>(); + private Map> myStates = new THashMap>(); private long myLastTimestamp = 0; private DirectoryStorageData myOriginalData; @@ -79,7 +77,7 @@ public class DirectoryStorageData { pathMacroSubstitutor.addUnknownMacros(componentName, unknownMacros); } - put(componentName, FileSystem.FILE_SYSTEM.createFile(file.getPath()), element, true); + put(componentName, new File(file.getPath()), element, true); } catch (IOException e) { LOG.info("Unable to load state", e); @@ -90,21 +88,23 @@ public class DirectoryStorageData { } } - public void put(final String componentName, final IFile file, final Element element, final boolean updateTimestamp) { + public void put(final String componentName, File file, final Element element, final boolean updateTimestamp) { LOG.assertTrue(componentName != null, String.format("Component name should not be null for file: %s", file == null ? "NULL!" : file.getPath())); - Map stateMap = myStates.get(componentName); + Map stateMap = myStates.get(componentName); if (stateMap == null) { - stateMap = new HashMap(); + stateMap = new THashMap(); myStates.put(componentName, stateMap); } stateMap.put(file, element); - if (updateTimestamp) updateLastTimestamp(file); + if (updateTimestamp) { + updateLastTimestamp(file); + } } - public void updateLastTimestamp(final IFile file) { - myLastTimestamp = Math.max(myLastTimestamp, file.getTimeStamp()); + public void updateLastTimestamp(File file) { + myLastTimestamp = Math.max(myLastTimestamp, file.lastModified()); if (myOriginalData != null) { myOriginalData.myLastTimestamp = myLastTimestamp; } @@ -114,22 +114,22 @@ public class DirectoryStorageData { return myLastTimestamp; } - public Map getAllStorageFiles() { - final Map allStorageFiles = new THashMap(); + public Map getAllStorageFiles() { + final Map allStorageFiles = new THashMap(); process(new StorageDataProcessor() { @Override - public void process(final String componentName, final IFile file, final Element element) { - allStorageFiles.put(file, file.getTimeStamp()); + public void process(final String componentName, final File file, final Element element) { + allStorageFiles.put(file, file.lastModified()); } }); return allStorageFiles; } - public void processComponent(@NotNull final String componentName, @NotNull final PairConsumer consumer) { - final Map map = myStates.get(componentName); + public void processComponent(@NotNull final String componentName, @NotNull final PairConsumer consumer) { + final Map map = myStates.get(componentName); if (map != null) { - for (IFile file : map.keySet()) { + for (File file : map.keySet()) { consumer.consume(file, map.get(file)); } } @@ -137,10 +137,10 @@ public class DirectoryStorageData { public void process(@NotNull final StorageDataProcessor processor) { for (final String componentName : myStates.keySet()) { - processComponent(componentName, new PairConsumer() { + processComponent(componentName, new PairConsumer() { @Override - public void consume(final IFile iFile, final Element element) { - processor.process(componentName, iFile, element); + public void consume(File file, Element element) { + processor.process(componentName, file, element); } }); } @@ -149,7 +149,7 @@ public class DirectoryStorageData { @Override protected DirectoryStorageData clone() { final DirectoryStorageData result = new DirectoryStorageData(); - result.myStates = new HashMap>(myStates); + result.myStates = new HashMap>(myStates); result.myLastTimestamp = myLastTimestamp; result.myOriginalData = this; return result; @@ -171,9 +171,9 @@ public class DirectoryStorageData { @Nullable public T getMergedState(String componentName, Class stateClass, StateSplitter splitter, @Nullable T mergeInto) { final List subElements = new ArrayList(); - processComponent(componentName, new PairConsumer() { + processComponent(componentName, new PairConsumer() { @Override - public void consume(final IFile iFile, final Element element) { + public void consume(File file, Element element) { final List children = element.getChildren(); assert children.size() == 1 : JDOMUtil.writeElement(element, File.separator); final Element subElement = (Element)children.get(0); @@ -190,6 +190,6 @@ public class DirectoryStorageData { } interface StorageDataProcessor { - void process(String componentName, IFile file, Element element); + void process(String componentName, File file, Element element); } } diff --git a/platform/testFramework/src/com/intellij/mock/Mock.java b/platform/testFramework/src/com/intellij/mock/Mock.java index 73d6538c52b9..a2768f2e1851 100644 --- a/platform/testFramework/src/com/intellij/mock/Mock.java +++ b/platform/testFramework/src/com/intellij/mock/Mock.java @@ -435,7 +435,7 @@ public class Mock { } @Override - public void setSelectedEditor(@NotNull VirtualFile file, String fileEditorProviderId) { + public void setSelectedEditor(@NotNull VirtualFile file, @NotNull String fileEditorProviderId) { } } diff --git a/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java b/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java index e4d4899b5fb3..a77ff2e315f4 100644 --- a/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java +++ b/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java @@ -77,6 +77,12 @@ public class ContainerUtilRt { return map; } + @NotNull + @Contract(pure=true) + public static Map newHashMap(int initialCapacity) { + return new com.intellij.util.containers.HashMap(initialCapacity); + } + @NotNull @Contract(pure=true) public static TreeMap newTreeMap() { diff --git a/platform/util-rt/src/com/intellij/util/containers/HashMap.java b/platform/util-rt/src/com/intellij/util/containers/HashMap.java index af41488814d0..fa8608f50bf8 100644 --- a/platform/util-rt/src/com/intellij/util/containers/HashMap.java +++ b/platform/util-rt/src/com/intellij/util/containers/HashMap.java @@ -21,12 +21,12 @@ import java.util.Map; public class HashMap extends java.util.HashMap { public HashMap() { } - public HashMap(int i, float v) { - super(i, v); + public HashMap(int initialCapacity, float loadFactor) { + super(initialCapacity, loadFactor); } - public HashMap(int i) { - super(i); + public HashMap(int initialCapacity) { + super(initialCapacity); } public HashMap(Map map) { diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 6599ec8bd8d7..9ce61924bc19 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -45,6 +45,15 @@ ide.firstStartup=true ide.debugMode=false ide.debugger.inline=false ide.debugger.inline.description=Enables variables view in editor +ide.debugger.inline.fg.color=61,128,101 +ide.debugger.inline.fg.color.description=Inline values foreground +ide.debugger.inline.dark.fg.color=61,128,101 +ide.debugger.inline.dark.fg.color.description=Inline values foreground for dark editor scheme +ide.debugger.inline.fg.modified.color=202,128,33 +ide.debugger.inline.fg.modified.color.description=Inline modified values foreground +ide.debugger.inline.dark.fg.modified.color=161,131,10 +ide.debugger.inline.dark.fg.modified.color.description=Inline modified values foreground for dark editor scheme + ide.debugMode.description=Record additional information to make bug reports more informative. ide.debug.minProgressTime=0 ide.forcedShowTooltip=alt diff --git a/platform/util/src/com/intellij/execution/configurations/CommandLineTokenizer.java b/platform/util/src/com/intellij/execution/configurations/CommandLineTokenizer.java index a62af9aa62dc..3f351b9a573e 100644 --- a/platform/util/src/com/intellij/execution/configurations/CommandLineTokenizer.java +++ b/platform/util/src/com/intellij/execution/configurations/CommandLineTokenizer.java @@ -20,9 +20,9 @@ import java.util.List; import java.util.StringTokenizer; /** - * Splits input String to tokens being aware of quoted tokens ("foo bar") and escaped spaces (foo\ bar), + * Splits input String to tokens being aware of quoted tokens ("foo bar") and escaped spaces & quotes (\"foo\ bar\"), * usually used for splitting command line to separate arguments that may contain space symbols. - * Escaped symbols are not handled so there's no way to get token that itself contains quotation mark. + * Space and quote are the only symbols that can be escaped */ public class CommandLineTokenizer extends StringTokenizer { @@ -103,8 +103,10 @@ public class CommandLineTokenizer extends StringTokenizer { do { while ((i = nextToken.indexOf('"')) >= 0) { - quotationMarks++; - buffer.append(nextToken.substring(0, i)); + boolean isEscapedQuote = i > 0 && nextToken.charAt(i - 1) == '\\'; + if (!isEscapedQuote) quotationMarks++; + buffer.append(nextToken.substring(0, isEscapedQuote ? i - 1 : i)); + if (isEscapedQuote) buffer.append('"'); nextToken = nextToken.substring(i + 1); } diff --git a/platform/util/src/com/intellij/openapi/application/PathManager.java b/platform/util/src/com/intellij/openapi/application/PathManager.java index 9956959f0e22..852f00cb7a68 100644 --- a/platform/util/src/com/intellij/openapi/application/PathManager.java +++ b/platform/util/src/com/intellij/openapi/application/PathManager.java @@ -418,7 +418,7 @@ public class PathManager { private static String getAbsolutePath(String path) { path = FileUtil.expandUserHome(path); - return FileUtil.toCanonicalPath(new File(FileUtil.toCanonicalPath(path)).getAbsolutePath()); + return FileUtil.toCanonicalPath(new File(path).getAbsolutePath()); } private static String trimPathQuotes(String path){ diff --git a/platform/util/src/com/intellij/openapi/util/JDOMExternalizer.java b/platform/util/src/com/intellij/openapi/util/JDOMExternalizer.java index 909c44db199b..cd5e8630a087 100644 --- a/platform/util/src/com/intellij/openapi/util/JDOMExternalizer.java +++ b/platform/util/src/com/intellij/openapi/util/JDOMExternalizer.java @@ -22,7 +22,10 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; public class JDOMExternalizer { private JDOMExternalizer() { @@ -66,7 +69,7 @@ public class JDOMExternalizer { return null; } - public static void writeMap(Element root, Mapmap, @NonNls @Nullable String rootName, @NonNls String entryName) { + public static void writeMap(Element root, Map map, @NonNls @Nullable String rootName, @NonNls String entryName) { Element mapRoot; if (StringUtil.isNotEmpty(rootName)) { mapRoot = new Element(rootName); @@ -106,6 +109,26 @@ public class JDOMExternalizer { } } + /** + * Saves a pack of strings to some attribte. I.e: [tag attr="value"] + * @param parent parent element (where to add newly created tags) + * @param nodeName node name (tag, in our example) + * @param attrName attribute name (attr, in our example) + * @param values a pack of values to add + * @see #loadStringsList(org.jdom.Element, String, String) + */ + public static void saveStringsList(@NotNull final Element parent, + @NotNull final String nodeName, + @NotNull final String attrName, + @NotNull final String... values) { + for (final String value : values) { + final Element node = new Element(nodeName); + node.setAttribute(attrName, value); + parent.addContent(node); + } + } + + @NotNull public static List loadStringsList(Element element, String rootName, String attrName) { final List paths = new LinkedList(); if (element != null) { diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index 7d3d6f557249..bc41f70e933a 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -1249,18 +1249,15 @@ public class FileUtil extends FileUtilRt { } public static boolean isWindowsAbsolutePath(@NotNull String pathString) { - if (pathString.length() >= 2 && Character.isLetter(pathString.charAt(0)) && pathString.charAt(1) == ':') { - return true; - } - return false; + return pathString.length() >= 2 && Character.isLetter(pathString.charAt(0)) && pathString.charAt(1) == ':'; } - @Contract("null -> null") + @Contract("null -> null; !null -> !null") public static String getLocationRelativeToUserHome(@Nullable String path) { return getLocationRelativeToUserHome(path, true); } - @Contract("null,_ -> null") + @Contract("null,_ -> null; !null,_ -> !null") public static String getLocationRelativeToUserHome(@Nullable String path, boolean unixOnly) { if (path == null) return null; diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index ab8ab2a33aa4..053bab6c86f2 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -68,6 +68,12 @@ public class ContainerUtil extends ContainerUtilRt { return ContainerUtilRt.newHashMap(keys, values); } + @NotNull + @Contract(pure=true) + public static Map newHashMap(int initialCapacity) { + return ContainerUtilRt.newHashMap(initialCapacity); + } + @NotNull @Contract(pure=true) public static TreeMap newTreeMap() { diff --git a/platform/util/src/com/intellij/util/messages/impl/MessageListenerList.java b/platform/util/src/com/intellij/util/messages/impl/MessageListenerList.java index d054416846a1..6d7bf76ccde7 100644 --- a/platform/util/src/com/intellij/util/messages/impl/MessageListenerList.java +++ b/platform/util/src/com/intellij/util/messages/impl/MessageListenerList.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. @@ -15,14 +15,14 @@ */ package com.intellij.util.messages.impl; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import com.intellij.util.containers.ConcurrentHashMap; import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.messages.Topic; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.util.Disposer; import org.jetbrains.annotations.NotNull; -import java.util.HashMap; import java.util.Map; /** @@ -31,7 +31,7 @@ import java.util.Map; public class MessageListenerList { private final MessageBus myMessageBus; private final Topic myTopic; - private final Map myListenerToConnectionMap = new HashMap(); + private final Map myListenerToConnectionMap = new ConcurrentHashMap(); public MessageListenerList(@NotNull MessageBus messageBus, @NotNull Topic topic) { myTopic = topic; diff --git a/platform/util/testSrc/com/intellij/execution/configurations/CommandLineTokenizerTest.java b/platform/util/testSrc/com/intellij/execution/configurations/CommandLineTokenizerTest.java new file mode 100644 index 000000000000..27235e4a132c --- /dev/null +++ b/platform/util/testSrc/com/intellij/execution/configurations/CommandLineTokenizerTest.java @@ -0,0 +1,54 @@ +/* + * 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.execution.configurations; + +import junit.framework.TestCase; + +public class CommandLineTokenizerTest extends TestCase { + public void testBasic() throws Exception { + assertTokens("a b", "a", "b"); + assertTokens("\"a b\"", "a b"); + assertTokens("a\" b\"", "a b"); + assertTokens("\"a b", "a b"); + assertTokens("a b\"", "a", "b"); + assertTokens("a b\" c", "a", "b c"); + assertTokens("\"a b\" c \"d e\"", "a b", "c", "d e"); + } + + public void testEscape() throws Exception { + assertTokens("a\\ b", true, "a b"); + assertTokens("\"a\\ b\"", true, "a\\ b"); + assertTokens("a\\ ", true, "a "); + + assertTokens("\\\"", "\""); + assertTokens("\"\\\" a \\\"\"", "\" a \""); + assertTokens("\\\"a b\\\"", "\"a", "b\""); + assertTokens("\\\"a\\ b\\\"", true, "\"a b\""); + } + + private static void assertTokens(String cmd, String... tokens) { + assertTokens(cmd, false, tokens); + } + + private static void assertTokens(String cmd, boolean handleEscapedWhitespaces, String... tokens) { + CommandLineTokenizer tokenizer = new CommandLineTokenizer(cmd, handleEscapedWhitespaces); + + assertEquals(tokens.length, tokenizer.countTokens()); + for (String token : tokens) { + assertEquals(token, tokenizer.nextToken()); + } + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurableProvider.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurableProvider.java new file mode 100644 index 000000000000..0ff9ef6c96d6 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsManagerConfigurableProvider.java @@ -0,0 +1,41 @@ +/* + * 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.vcs.configurable; + +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurableProvider; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.ProjectLevelVcsManager; +import org.jetbrains.annotations.NotNull; + +public final class VcsManagerConfigurableProvider extends ConfigurableProvider { + private final Project myProject; + + public VcsManagerConfigurableProvider(Project project) { + myProject = project; + } + + @NotNull + @Override + public Configurable createConfigurable() { + return new VcsManagerConfigurable(myProject); + } + + @Override + public boolean canCreateConfigurable() { + return ProjectLevelVcsManager.getInstance(myProject).getAllVcss().length > 0; + } +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java index e73564095b21..b9a58844585a 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/XDebuggerEditorLinePainter.java @@ -18,6 +18,7 @@ package com.intellij.xdebugger.impl.evaluate; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.EditorLinePainter; import com.intellij.openapi.editor.LineExtensionInfo; +import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; @@ -25,10 +26,8 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.Gray; -import com.intellij.ui.JBColor; -import com.intellij.ui.SimpleColoredText; -import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.*; +import com.intellij.util.NotNullProducer; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.frame.presentation.XValuePresentation; @@ -142,12 +141,33 @@ public class XDebuggerEditorLinePainter extends EditorLinePainter { return -1; } + private static boolean isDarkEditor() { + Color bg = EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground(); + return ColorUtil.isDark(bg); + } + public static JBColor getForeground() { - return new JBColor(new Color(61, 128, 101), new Color(61, 128, 101)); + return new JBColor(new NotNullProducer() { + @SuppressWarnings("UseJBColor") + @NotNull + @Override + public Color produce() { + return isDarkEditor() ? Registry.getColor("ide.debugger.inline.dark.fg.color", new Color(0x3d8065)) + : Registry.getColor("ide.debugger.inline.fg.color", new Color(0x3d8065)); + } + }); } public static JBColor getChangedForeground() { - return new JBColor(new Color(202, 128, 33), new Color(161, 131, 10)); + return new JBColor(new NotNullProducer() { + @SuppressWarnings("UseJBColor") + @NotNull + @Override + public Color produce() { + return isDarkEditor() ? Registry.getColor("ide.debugger.inline.dark.fg.modified.color", new Color(0xa1830a)) + : Registry.getColor("ide.debugger.inline.fg.modified.color", new Color(0xca8021)); + } + }); } static class Variable { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryContainer.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryContainer.java index c7c5af9f6fb4..2851c701ef70 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryContainer.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryContainer.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. @@ -170,7 +170,7 @@ abstract class DebuggerTreeWithHistoryContainer { } @Override - public void onFailure(Throwable t) { + public void onFailure(@NotNull Throwable t) { LOG.debug(t); } }); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java new file mode 100644 index 000000000000..bb747f92eab7 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/settings/DebuggerConfigurableProvider.java @@ -0,0 +1,34 @@ +/* + * 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.xdebugger.impl.settings; + +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurableProvider; +import com.intellij.xdebugger.breakpoints.XBreakpointType; +import org.jetbrains.annotations.NotNull; + +public final class DebuggerConfigurableProvider extends ConfigurableProvider { + @NotNull + @Override + public Configurable createConfigurable() { + return new DebuggerConfigurable(); + } + + @Override + public boolean canCreateConfigurable() { + return XBreakpointType.EXTENSION_POINT_NAME.getExtensions().length != 0; + } +} diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/Ambiguity.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/Ambiguity.java index 6df5c30ae69a..e8be7a9d0b0c 100644 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/Ambiguity.java +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/Ambiguity.java @@ -2,14 +2,14 @@ interface I1 { void m(); } -interface I2 { - X m(); +interface I2 { + void m(); } class Ambiguity1 { static void m(I1 i1) {} - static void m(I2 i2) {} + static void m(I2 i2) {} { m(()->{throw new AssertionError();}); diff --git a/plugins/ShortcutPromoter/src/com/intellij/promoter/ShortcutPromoterManager.java b/plugins/ShortcutPromoter/src/com/intellij/promoter/ShortcutPromoterManager.java index 227d96245080..8b192a78beb7 100644 --- a/plugins/ShortcutPromoter/src/com/intellij/promoter/ShortcutPromoterManager.java +++ b/plugins/ShortcutPromoter/src/com/intellij/promoter/ShortcutPromoterManager.java @@ -97,10 +97,6 @@ public class ShortcutPromoterManager implements ApplicationComponent, AnActionLi @Nullable @Override public Element getState() { - if (myState.isEmpty()) { - return null; - } - final Element actions = new Element("actions"); for (String id : myState.keySet()) { final Element action = new Element("action"); diff --git a/plugins/devkit/src/testAssistant/TestLocationDataRule.java b/plugins/devkit/src/testAssistant/TestLocationDataRule.java index 6dccd0f808da..74c9d34c5a96 100644 --- a/plugins/devkit/src/testAssistant/TestLocationDataRule.java +++ b/plugins/devkit/src/testAssistant/TestLocationDataRule.java @@ -23,6 +23,7 @@ import com.intellij.execution.junit2.info.MethodLocation; import com.intellij.ide.impl.dataRules.GetDataRule; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataProvider; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; @@ -58,6 +59,8 @@ public class TestLocationDataRule implements GetDataRule { @NotNull protected static List collectRelativeLocations(Project project, VirtualFile file) { + if (DumbService.isDumb(project)) return Collections.emptyList(); + final List locations = new ArrayList(); final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); if (fileIndex.isInContent(file) && !fileIndex.isInSource(file) && !fileIndex.isInLibraryClasses(file)) { diff --git a/plugins/git4idea/src/git4idea/config/GitVcsPanel.java b/plugins/git4idea/src/git4idea/config/GitVcsPanel.java index a8ebfe66140f..3a4cab90deb3 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsPanel.java +++ b/plugins/git4idea/src/git4idea/config/GitVcsPanel.java @@ -15,18 +15,17 @@ */ package git4idea.config; +import com.intellij.dvcs.branch.DvcsBranchSync; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; -import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.components.JBCheckBox; import git4idea.GitVcs; import git4idea.i18n.GitBundle; import git4idea.repo.GitRepositoryManager; -import git4idea.ui.branch.GitBranchSyncSetting; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -119,7 +118,7 @@ public class GitVcsPanel { myGitField.setText(settings.getAppSettings().getPathToGit()); mySSHExecutableComboBox.setSelectedItem(settings.isIdeaSsh() ? IDEA_SSH : NATIVE_SSH); myAutoUpdateIfPushRejected.setSelected(settings.autoUpdateIfPushRejected()); - mySyncBranchControl.setSelected(settings.getSyncSetting() == GitBranchSyncSetting.SYNC); + mySyncBranchControl.setSelected(settings.getSyncSetting() == DvcsBranchSync.SYNC); myAutoCommitOnCherryPick.setSelected(settings.isAutoCommitOnCherryPick()); myWarnAboutCrlf.setSelected(settings.warnAboutCrlf()); } @@ -133,7 +132,7 @@ public class GitVcsPanel { return !settings.getAppSettings().getPathToGit().equals(getCurrentExecutablePath()) || (settings.isIdeaSsh() != IDEA_SSH.equals(mySSHExecutableComboBox.getSelectedItem())) || !settings.autoUpdateIfPushRejected() == myAutoUpdateIfPushRejected.isSelected() || - ((settings.getSyncSetting() == GitBranchSyncSetting.SYNC) != mySyncBranchControl.isSelected() || + ((settings.getSyncSetting() == DvcsBranchSync.SYNC) != mySyncBranchControl.isSelected() || settings.isAutoCommitOnCherryPick() != myAutoCommitOnCherryPick.isSelected() || settings.warnAboutCrlf() != myWarnAboutCrlf.isSelected()); } @@ -151,7 +150,7 @@ public class GitVcsPanel { GitVcsApplicationSettings.SshExecutable.NATIVE_SSH); settings.setAutoUpdateIfPushRejected(myAutoUpdateIfPushRejected.isSelected()); - settings.setSyncSetting(mySyncBranchControl.isSelected() ? GitBranchSyncSetting.SYNC : GitBranchSyncSetting.DONT); + settings.setSyncSetting(mySyncBranchControl.isSelected() ? DvcsBranchSync.SYNC : DvcsBranchSync.DONT); settings.setAutoCommitOnCherryPick(myAutoCommitOnCherryPick.isSelected()); settings.setWarnAboutCrlf(myWarnAboutCrlf.isSelected()); } diff --git a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java index 1b5860631e59..de268c372327 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java +++ b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java @@ -15,12 +15,13 @@ */ package git4idea.config; +import com.intellij.dvcs.branch.DvcsBranchSync; +import com.intellij.dvcs.branch.DvcsSyncBranchSettings; import com.intellij.lifecycle.PeriodicalTasksCloser; import com.intellij.openapi.components.*; import com.intellij.openapi.project.Project; import com.intellij.util.ArrayUtil; import git4idea.reset.GitResetMode; -import git4idea.ui.branch.GitBranchSyncSetting; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,7 +34,7 @@ import java.util.Map; * Git VCS settings */ @State(name = "Git.Settings", roamingType = RoamingType.DISABLED, storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)}) -public class GitVcsSettings implements PersistentStateComponent { +public class GitVcsSettings implements PersistentStateComponent, DvcsSyncBranchSettings { private static final int PREVIOUS_COMMIT_AUTHORS_LIMIT = 16; // Limit for previous commit authors @@ -56,7 +57,7 @@ public class GitVcsSettings implements PersistentStateComponent RECENT_BRANCH_BY_REPOSITORY = new HashMap(); public String RECENT_COMMON_BRANCH = null; @@ -128,11 +129,11 @@ public class GitVcsSettings implements PersistentStateComponent */ -class GitBranchPopup { - - private final Project myProject; - private final GitRepositoryManager myRepositoryManager; - private final GitVcsSettings myVcsSettings; - private final GitVcs myVcs; - private final GitMultiRootBranchConfig myMultiRootBranchConfig; - - private final GitRepository myCurrentRepository; - private final ListPopupImpl myPopup; - - ListPopup asListPopup() { - return myPopup; - } +class GitBranchPopup extends DvcsBranchPopup { /** * @param currentRepository Current repository, which means the repository of the currently open or selected file. * In the case of synchronized branch operations current repository matter much less, but sometimes is used, * for example, it is preselected in the repositories combobox in the compare branches dialog. */ - static GitBranchPopup getInstance(@NotNull Project project, @NotNull GitRepository currentRepository) { - return new GitBranchPopup(project, currentRepository); - } - - private GitBranchPopup(@NotNull Project project, @NotNull GitRepository currentRepository) { - myProject = project; - myCurrentRepository = currentRepository; - myRepositoryManager = GitUtil.getRepositoryManager(project); - myVcs = GitVcs.getInstance(project); - myVcsSettings = GitVcsSettings.getInstance(myProject); - - myMultiRootBranchConfig = new GitMultiRootBranchConfig(myRepositoryManager.getRepositories()); - - String title = createPopupTitle(currentRepository); - + static GitBranchPopup getInstance(@NotNull final Project project, @NotNull GitRepository currentRepository) { + final GitVcsSettings vcsSettings = GitVcsSettings.getInstance(project); Condition preselectActionCondition = new Condition() { @Override public boolean value(AnAction action) { + if (action instanceof GitBranchPopupActions.LocalBranchActions) { GitBranchPopupActions.LocalBranchActions branchAction = (GitBranchPopupActions.LocalBranchActions)action; String branchName = branchAction.getBranchName(); @@ -93,10 +58,10 @@ class GitBranchPopup { String recentBranch; List repositories = branchAction.getRepositories(); if (repositories.size() == 1) { - recentBranch = myVcsSettings.getRecentBranchesByRepository().get(repositories.iterator().next().getRoot().getPath()); + recentBranch = vcsSettings.getRecentBranchesByRepository().get(repositories.iterator().next().getRoot().getPath()); } else { - recentBranch = myVcsSettings.getRecentCommonBranch(); + recentBranch = vcsSettings.getRecentCommonBranch(); } if (recentBranch != null && recentBranch.equals(branchName)) { @@ -106,37 +71,19 @@ class GitBranchPopup { return false; } }; - - myPopup = new BranchActionGroupPopup(title, project, preselectActionCondition, createActions()); - - initBranchSyncPolicyIfNotInitialized(); - setCurrentBranchInfo(); - warnThatBranchesDivergedIfNeeded(); + return new GitBranchPopup(currentRepository, GitUtil.getRepositoryManager(project), vcsSettings, preselectActionCondition); } - private void initBranchSyncPolicyIfNotInitialized() { - if (myRepositoryManager.moreThanOneRoot() && myVcsSettings.getSyncSetting() == GitBranchSyncSetting.NOT_DECIDED) { - if (!myMultiRootBranchConfig.diverged()) { - notifyAboutSyncedBranches(); - myVcsSettings.setSyncSetting(GitBranchSyncSetting.SYNC); - } - else { - myVcsSettings.setSyncSetting(GitBranchSyncSetting.DONT); - } - } + private GitBranchPopup(@NotNull GitRepository currentRepository, + @NotNull GitRepositoryManager repositoryManager, + @NotNull GitVcsSettings vcsSettings, + @NotNull Condition preselectActionCondition) { + super(currentRepository, repositoryManager, new GitMultiRootBranchConfig(repositoryManager.getRepositories()), vcsSettings, + preselectActionCondition); } - @NotNull - private String createPopupTitle(@NotNull GitRepository currentRepository) { - String title = "Git Branches"; - if (myRepositoryManager.moreThanOneRoot() && - (myMultiRootBranchConfig.diverged() || myVcsSettings.getSyncSetting() == GitBranchSyncSetting.DONT)) { - title += " in " + DvcsUtil.getShortRepositoryName(currentRepository); - } - return title; - } - - private void setCurrentBranchInfo() { + @Override + protected void setCurrentBranchInfo() { String currentBranchText = "Current branch"; if (myRepositoryManager.moreThanOneRoot()) { if (myMultiRootBranchConfig.diverged()) { @@ -153,55 +100,16 @@ class GitBranchPopup { myPopup.setAdText(currentBranchText, SwingConstants.CENTER); } - private void notifyAboutSyncedBranches() { - String description = "You have several Git roots in the project and they all are checked out at the same branch. " + - "We've enabled synchronous branch control for the project.
" + - "If you wish to control branches in different roots separately, " + - "you may disable the setting."; - NotificationListener listener = new NotificationListener() { - @Override - public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { - if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - ShowSettingsUtil.getInstance().showSettingsDialog(myProject, myVcs.getConfigurable().getDisplayName()); - if (myVcsSettings.getSyncSetting() == GitBranchSyncSetting.DONT) { - notification.expire(); - } - } - } - }; - VcsNotifier.getInstance(myProject).notifyImportantInfo("Synchronous branch control enabled", description, listener); - } - - private ActionGroup createActions() { - DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); - GitRepositoryManager repositoryManager = myRepositoryManager; - if (repositoryManager.moreThanOneRoot()) { - if (userWantsSyncControl()) { - fillWithCommonRepositoryActions(popupGroup, repositoryManager); - } - else { - fillPopupWithCurrentRepositoryActions(popupGroup, createRepositoriesActions()); - } - } - else { - fillPopupWithCurrentRepositoryActions(popupGroup, null); - } - popupGroup.addSeparator(); - return popupGroup; - } - - private boolean userWantsSyncControl() { - return (myVcsSettings.getSyncSetting() != GitBranchSyncSetting.DONT); - } - - private void fillWithCommonRepositoryActions(DefaultActionGroup popupGroup, GitRepositoryManager repositoryManager) { + @Override + protected void fillWithCommonRepositoryActions(@NotNull DefaultActionGroup popupGroup, + @NotNull AbstractRepositoryManager repositoryManager) { List allRepositories = repositoryManager.getRepositories(); popupGroup.add(new GitBranchPopupActions.GitNewBranchAction(myProject, allRepositories)); popupGroup.addAll(createRepositoriesActions()); popupGroup.addSeparator("Common Local Branches"); - for (String branch : myMultiRootBranchConfig.getLocalBranches()) { + for (String branch : myMultiRootBranchConfig.getLocalBranchNames()) { List repositories = filterRepositoriesNotOnThisBranch(branch, allRepositories); if (!repositories.isEmpty()) { popupGroup.add(new GitBranchPopupActions.LocalBranchActions(myProject, repositories, branch, myCurrentRepository)); @@ -209,30 +117,14 @@ class GitBranchPopup { } popupGroup.addSeparator("Common Remote Branches"); - for (String branch : myMultiRootBranchConfig.getRemoteBranches()) { + for (String branch : ((GitMultiRootBranchConfig)myMultiRootBranchConfig).getRemoteBranches()) { popupGroup.add(new GitBranchPopupActions.RemoteBranchActions(myProject, allRepositories, branch, myCurrentRepository)); } } @NotNull - private static List filterRepositoriesNotOnThisBranch(@NotNull final String branch, - @NotNull List allRepositories) { - return ContainerUtil.filter(allRepositories, new Condition() { - @Override - public boolean value(GitRepository repository) { - GitLocalBranch currentBranch = repository.getCurrentBranch(); - return currentBranch == null || !branch.equals(currentBranch.getName()); - } - }); - } - - private void warnThatBranchesDivergedIfNeeded() { - if (myRepositoryManager.moreThanOneRoot() && myMultiRootBranchConfig.diverged() && userWantsSyncControl()) { - myPopup.setWarning("Branches have diverged"); - } - } - - private DefaultActionGroup createRepositoriesActions() { + @Override + protected DefaultActionGroup createRepositoriesActions() { DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); popupGroup.addSeparator("Repositories"); for (GitRepository repository : myRepositoryManager.getRepositories()) { @@ -243,11 +135,8 @@ class GitBranchPopup { return popupGroup; } - private boolean highlightCurrentRepo() { - return !userWantsSyncControl() || myMultiRootBranchConfig.diverged(); - } - - private void fillPopupWithCurrentRepositoryActions(@NotNull DefaultActionGroup popupGroup, @Nullable DefaultActionGroup actions) { + @Override + protected void fillPopupWithCurrentRepositoryActions(@NotNull DefaultActionGroup popupGroup, @Nullable DefaultActionGroup actions) { popupGroup.addAll(new GitBranchPopupActions(myCurrentRepository.getProject(), myCurrentRepository).createActions(actions)); } } diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitMultiRootBranchConfig.java b/plugins/git4idea/src/git4idea/ui/branch/GitMultiRootBranchConfig.java index ba4dd2aab369..18076a1b9a61 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitMultiRootBranchConfig.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitMultiRootBranchConfig.java @@ -15,8 +15,8 @@ */ package git4idea.ui.branch; +import com.intellij.dvcs.branch.DvcsMultiRootBranchConfig; import com.intellij.util.containers.ContainerUtil; -import git4idea.GitBranch; import git4idea.GitLocalBranch; import git4idea.GitRemoteBranch; import git4idea.branch.GitBranchUtil; @@ -32,54 +32,17 @@ import java.util.Collections; /** * @author Kirill Likhodedov */ -public class GitMultiRootBranchConfig { - - private final Collection myRepositories; +public class GitMultiRootBranchConfig extends DvcsMultiRootBranchConfig { public GitMultiRootBranchConfig(@NotNull Collection repositories) { - myRepositories = repositories; + super(repositories); } - boolean diverged() { - return getCurrentBranch() == null; - } - - @Nullable - public String getCurrentBranch() { - String commonBranch = null; - for (GitRepository repository : myRepositories) { - GitBranch branch = repository.getCurrentBranch(); - if (branch == null) { - return null; - } - // NB: if all repositories are in the rebasing state on the same branches, this branch is returned - if (commonBranch == null) { - commonBranch = branch.getName(); - } else if (!commonBranch.equals(branch.getName())) { - return null; - } - } - return commonBranch; - } - - @Nullable - GitRepository.State getState() { - GitRepository.State commonState = null; - for (GitRepository repository : myRepositories) { - GitRepository.State state = repository.getState(); - if (commonState == null) { - commonState = state; - } else if (!commonState.equals(state)) { - return null; - } - } - return commonState; - } - + @Override @NotNull - Collection getLocalBranches() { + public Collection getLocalBranchNames() { return GitBranchUtil.getCommonBranches(myRepositories, true); - } + } @NotNull Collection getRemoteBranches() { diff --git a/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java b/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java index 2ce560800066..39d5946c90ff 100644 --- a/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java +++ b/plugins/git4idea/tests/git4idea/log/GitRefManagerTest.java @@ -284,6 +284,12 @@ public class GitRefManagerTest extends UsefulTestCase { throw new UnsupportedOperationException(); } + @Nullable + @Override + public String getCurrentBranchName() { + throw new UnsupportedOperationException(); + } + @Nullable @Override public AbstractVcs getVcs() { diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml index 26b69326a703..dc32359a4aec 100644 --- a/plugins/hg4idea/src/META-INF/plugin.xml +++ b/plugins/hg4idea/src/META-INF/plugin.xml @@ -75,7 +75,7 @@ - + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectSettings.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectSettings.java index 936587d19755..8abac1bb0b1e 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectSettings.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgProjectSettings.java @@ -12,6 +12,8 @@ // limitations under the License. package org.zmlx.hg4idea; +import com.intellij.dvcs.branch.DvcsBranchSync; +import com.intellij.dvcs.branch.DvcsSyncBranchSettings; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; @@ -24,7 +26,7 @@ import org.jetbrains.annotations.NotNull; name = "hg4idea.settings", storages = @Storage(file = StoragePathMacros.WORKSPACE_FILE) ) -public class HgProjectSettings implements PersistentStateComponent { +public class HgProjectSettings implements PersistentStateComponent, DvcsSyncBranchSettings { @NotNull private final HgGlobalSettings myAppSettings; @NotNull private final Project myProject; @@ -37,10 +39,12 @@ public class HgProjectSettings implements PersistentStateComponent - * The popup which allows to quickly switch and control Hg branches. - *

- *

- * Use {@link #asListPopup()} to achieve the {@link com.intellij.openapi.ui.popup.ListPopup} itself. - *

- * - * @author NadyaZabrodina - */ -public class HgBranchPopup { - - private final Project myProject; - - private final HgRepository myCurrentRepository; - private final ListPopupImpl myPopup; - - public ListPopup asListPopup() { - return myPopup; - } - - /** - * @param currentRepository Current repository, which means the repository of the currently open or selected file. - */ - public static HgBranchPopup getInstance(@NotNull Project project, @NotNull HgRepository currentRepository) { - return new HgBranchPopup(project, currentRepository); - } - - private HgBranchPopup(@NotNull Project project, @NotNull HgRepository currentRepository) { - myProject = project; - myCurrentRepository = currentRepository; - String title = createPopupTitle(currentRepository); - - Condition preselectActionCondition = new Condition() { - @Override - public boolean value(AnAction action) { - return false; - } - }; - myPopup = new BranchActionGroupPopup(title, project, preselectActionCondition, createActions()); - setCurrentBranchInfo(); - } - - - @NotNull - private static String createPopupTitle(@NotNull HgRepository currentRepository) { - String title = "Hg Branches"; - title += " in " + DvcsUtil.getShortRepositoryName(currentRepository); - return title; - } - - private void setCurrentBranchInfo() { - String branchText = "Current branch : "; - //always display heavy branch name for additional info // - myPopup.setAdText(branchText + myCurrentRepository.getCurrentBranch(), SwingConstants.CENTER); - } - - - private ActionGroup createActions() { - DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); - fillPopupWithCurrentRepositoryActions(popupGroup, createRepositoriesActions()); - popupGroup.addSeparator(); - return popupGroup; - } - - - @Nullable - private DefaultActionGroup createRepositoriesActions() { - List repositories = HgUtil.getHgRepositories(myProject); - if (repositories.size() == 1) { - return null; // if project has only one repository all branches, bookmarks and actions should be inline and no repository group needed - } - DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); - popupGroup.addSeparator("Repositories"); - boolean isMultiRepoConfig = repositories.size() > 1; - for (VirtualFile repository : repositories) { - HgRepository repo = HgUtil.getRepositoryManager(myProject).getRepositoryForRoot(repository); - if (repo != null) { - popupGroup.add(new RootAction(repo, isMultiRepoConfig ? myCurrentRepository : null, - new HgBranchPopupActions(repo.getProject(), repo).createActions(null), - HgUtil.getDisplayableBranchOrBookmarkText(repo))); - } - } - return popupGroup; - } - - protected void fillPopupWithCurrentRepositoryActions(@NotNull DefaultActionGroup popupGroup, @Nullable DefaultActionGroup actions) { - popupGroup.addAll(new HgBranchPopupActions(myProject, myCurrentRepository).createActions(actions)); - } -} - diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java deleted file mode 100644 index c79ae1ca0b7c..000000000000 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCommonBranchActions.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.zmlx.hg4idea.action; - -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.Task; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.VcsNotifier; -import com.intellij.openapi.vcs.update.UpdatedFiles; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.zmlx.hg4idea.HgVcs; -import org.zmlx.hg4idea.HgVcsMessages; -import org.zmlx.hg4idea.command.HgMergeCommand; -import org.zmlx.hg4idea.command.HgUpdateCommand; -import org.zmlx.hg4idea.execution.HgCommandResult; -import org.zmlx.hg4idea.provider.update.HgConflictResolver; -import org.zmlx.hg4idea.provider.update.HgHeadMerger; -import org.zmlx.hg4idea.repo.HgRepository; -import org.zmlx.hg4idea.util.HgErrorUtil; - -public class HgCommonBranchActions extends ActionGroup { - - @NotNull protected final Project myProject; - @NotNull protected String myBranchName; - @NotNull protected final HgRepository mySelectedRepository; - - HgCommonBranchActions(@NotNull Project project, @NotNull HgRepository selectedRepository, @NotNull String branchName) { - super("", true); - myProject = project; - myBranchName = branchName; - mySelectedRepository = selectedRepository; - getTemplatePresentation().setText(myBranchName, false); // no mnemonics - } - - @NotNull - @Override - public AnAction[] getChildren(@Nullable AnActionEvent e) { - return new AnAction[]{ - new UpdateAction(myProject, mySelectedRepository, myBranchName), - new MergeAction(myProject, mySelectedRepository, myBranchName) - }; - } - - private static class MergeAction extends HgBranchAbstractAction { - - public MergeAction(@NotNull Project project, - @NotNull HgRepository selectedRepository, - @NotNull String branchName) { - super(project, "Merge", selectedRepository, branchName); - } - - @Override - public void actionPerformed(AnActionEvent e) { - FileDocumentManager.getInstance().saveAllDocuments(); - final UpdatedFiles updatedFiles = UpdatedFiles.create(); - final HgMergeCommand hgMergeCommand = new HgMergeCommand(myProject, mySelectedRepository.getRoot()); - hgMergeCommand.setRevision(myBranchName);//there is no difference between branch or revision or bookmark as parameter to merge, - // we need just a string - new Task.Backgroundable(myProject, "Merging changes...") { - @Override - public void run(@NotNull ProgressIndicator indicator) { - try { - new HgHeadMerger(myProject, hgMergeCommand) - .merge(mySelectedRepository.getRoot()); - new HgConflictResolver(myProject, updatedFiles).resolve(mySelectedRepository.getRoot()); - } - - catch (VcsException exception) { - assert myProject != null; // myProject couldn't be null, see annotation for Merge action - if (exception.isWarning()) { - VcsNotifier.getInstance(myProject).notifyWarning("Warning during merge", exception.getMessage()); - } - else { - VcsNotifier.getInstance(myProject).notifyError("Exception during merge", exception.getMessage()); - } - } - catch (Exception e1) { - HgAbstractGlobalAction.handleException(myProject, e1); - } - } - }.queue(); - } - } - - private static class UpdateAction extends HgBranchAbstractAction { - - public UpdateAction(@NotNull Project project, - @NotNull HgRepository selectedRepository, - @NotNull String branchName) { - super(project, "Update", selectedRepository, branchName); - } - - @Override - public void actionPerformed(AnActionEvent e) { - final VirtualFile repository = mySelectedRepository.getRoot(); - FileDocumentManager.getInstance().saveAllDocuments(); - final HgUpdateCommand hgUpdateCommand = new HgUpdateCommand(myProject, repository); - hgUpdateCommand.setBranch(myBranchName); - new Task.Backgroundable(myProject, HgVcsMessages.message("action.hg4idea.updateTo.description", myBranchName)) { - @Override - public void run(@NotNull ProgressIndicator indicator) { - HgCommandResult result = hgUpdateCommand.execute(); - assert myProject != null; // myProject couldn't be null, see annotation for updateTo action - if (HgErrorUtil.hasErrorsInCommandExecution(result)) { - new HgCommandResultNotifier(myProject).notifyError(result, "", "Update failed"); - new HgConflictResolver(myProject).resolve(repository); - } - myProject.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(myProject, null); - } - }.queue(); - } - } -} \ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchAbstractAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchAbstractAction.java similarity index 83% rename from plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchAbstractAction.java rename to plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchAbstractAction.java index 78b67013ed54..3998dedd0cc5 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchAbstractAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchAbstractAction.java @@ -13,24 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.zmlx.hg4idea.action; +package org.zmlx.hg4idea.branch; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.repo.HgRepository; +import java.util.List; + public abstract class HgBranchAbstractAction extends DumbAwareAction { @NotNull protected final Project myProject; - @NotNull protected final HgRepository mySelectedRepository; + @NotNull protected final List myRepositories; @NotNull protected final String myBranchName; public HgBranchAbstractAction(@NotNull Project project, @NotNull String title, - @NotNull HgRepository selectedRepository, + @NotNull List repositories, @NotNull String branchName) { super(title); myProject = project; - mySelectedRepository = selectedRepository; + myRepositories = repositories; myBranchName = branchName; } } \ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopup.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopup.java new file mode 100644 index 000000000000..c0d6f58d5e0e --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopup.java @@ -0,0 +1,119 @@ +/* + * Copyright 2000-2013 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 org.zmlx.hg4idea.branch; + +import com.intellij.dvcs.branch.DvcsBranchPopup; +import com.intellij.dvcs.repo.AbstractRepositoryManager; +import com.intellij.dvcs.ui.RootAction; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.HgProjectSettings; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.repo.HgRepositoryManager; +import org.zmlx.hg4idea.util.HgUtil; + +import javax.swing.*; +import java.util.List; + +/** + *

+ * The popup which allows to quickly switch and control Hg branches. + *

+ *

+ * Use {@link #asListPopup()} to achieve the {@link com.intellij.openapi.ui.popup.ListPopup} itself. + *

+ */ +public class HgBranchPopup extends DvcsBranchPopup { + + /** + * @param currentRepository Current repository, which means the repository of the currently open or selected file. + */ + public static HgBranchPopup getInstance(@NotNull Project project, @NotNull HgRepository currentRepository) { + + HgRepositoryManager manager = HgUtil.getRepositoryManager(project); + HgProjectSettings hgProjectSettings = ServiceManager.getService(project, HgProjectSettings.class); + HgMultiRootBranchConfig hgMultiRootBranchConfig = new HgMultiRootBranchConfig(manager.getRepositories()); + + Condition preselectActionCondition = new Condition() { + @Override + public boolean value(AnAction action) { + return false; + } + }; + return new HgBranchPopup(currentRepository, manager, hgMultiRootBranchConfig, hgProjectSettings, + preselectActionCondition); + } + + private HgBranchPopup(@NotNull HgRepository currentRepository, + @NotNull HgRepositoryManager repositoryManager, + @NotNull HgMultiRootBranchConfig hgMultiRootBranchConfig, @NotNull HgProjectSettings vcsSettings, + @NotNull Condition preselectActionCondition) { + super(currentRepository, repositoryManager, hgMultiRootBranchConfig, vcsSettings, preselectActionCondition); + } + + protected void setCurrentBranchInfo() { + String branchText = "Current branch : "; + //always display heavy branch name for additional info // + myPopup.setAdText(branchText + myCurrentRepository.getCurrentBranch(), SwingConstants.CENTER); + } + + @Override + protected void fillWithCommonRepositoryActions(@NotNull DefaultActionGroup popupGroup, + @NotNull AbstractRepositoryManager repositoryManager) { + List allRepositories = repositoryManager.getRepositories(); + popupGroup.add(new HgBranchPopupActions.HgNewBranchAction(myProject, allRepositories, myCurrentRepository)); + popupGroup.addAction(new HgBranchPopupActions.HgNewBookmarkAction(myProject, allRepositories, myCurrentRepository)); + popupGroup.addAction(new HgBranchPopupActions.HgShowUnnamedHeadsForCurrentBranchAction(myProject, myCurrentRepository)); + popupGroup.addAll(createRepositoriesActions()); + + popupGroup.addSeparator("Common Branches"); + for (String branch : myMultiRootBranchConfig.getLocalBranchNames()) { + List repositories = filterRepositoriesNotOnThisBranch(branch, allRepositories); + if (!repositories.isEmpty()) { + popupGroup.add(new HgCommonBranchActions(myProject, repositories, branch)); + } + } + popupGroup.addSeparator("Common Bookmarks"); + for (String branch : ((HgMultiRootBranchConfig)myMultiRootBranchConfig).getBookmarkNames()) { + List repositories = filterRepositoriesNotOnThisBranch(branch, allRepositories); + if (!repositories.isEmpty()) { + popupGroup.add(new HgBranchPopupActions.BookmarkActions(myProject, repositories, branch)); + } + } + } + + @NotNull + protected DefaultActionGroup createRepositoriesActions() { + DefaultActionGroup popupGroup = new DefaultActionGroup(null, false); + popupGroup.addSeparator("Repositories"); + for (HgRepository repository : myRepositoryManager.getRepositories()) { + popupGroup.add(new RootAction(repository, highlightCurrentRepo() ? myCurrentRepository : null, + new HgBranchPopupActions(repository.getProject(), repository).createActions(null), + HgUtil.getDisplayableBranchOrBookmarkText(repository))); + } + return popupGroup; + } + + protected void fillPopupWithCurrentRepositoryActions(@NotNull DefaultActionGroup popupGroup, @Nullable DefaultActionGroup actions) { + popupGroup.addAll(new HgBranchPopupActions(myProject, myCurrentRepository).createActions(actions)); + } +} + diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopupActions.java similarity index 77% rename from plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java rename to plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopupActions.java index 45dd12bd9c81..10b97235f559 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchPopupActions.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.zmlx.hg4idea.action; +package org.zmlx.hg4idea.branch; import com.intellij.dvcs.DvcsUtil; import com.intellij.dvcs.repo.Repository; @@ -35,6 +35,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.HgNameWithHashInfo; import org.zmlx.hg4idea.HgRevisionNumber; +import org.zmlx.hg4idea.action.HgAbstractGlobalAction; +import org.zmlx.hg4idea.action.HgCommandResultNotifier; import org.zmlx.hg4idea.command.HgBookmarkCommand; import org.zmlx.hg4idea.command.HgBranchCreateCommand; import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand; @@ -73,7 +75,7 @@ public class HgBranchPopupActions { List bookmarkNames = getNamesWithoutHashes(myRepository.getBookmarks()); String currentBookmark = myRepository.getCurrentBookmark(); for (String bookmark : bookmarkNames) { - AnAction bookmarkAction = new BookmarkActions(myProject, myRepository, bookmark); + AnAction bookmarkAction = new BookmarkActions(myProject, Collections.singletonList(myRepository), bookmark); if (bookmark.equals(currentBookmark)) { bookmarkAction.getTemplatePresentation().setIcon(PlatformIcons.CHECK_ICON); } @@ -85,13 +87,13 @@ public class HgBranchPopupActions { Collections.sort(branchNamesList); for (String branch : branchNamesList) { if (!branch.equals(myRepository.getCurrentBranch())) { // don't show current branch in the list - popupGroup.add(new HgCommonBranchActions(myProject, myRepository, branch)); + popupGroup.add(new HgCommonBranchActions(myProject, Collections.singletonList(myRepository), branch)); } } return popupGroup; } - private static class HgNewBranchAction extends NewBranchAction { + public static class HgNewBranchAction extends NewBranchAction { @NotNull final HgRepository myPreselectedRepo; HgNewBranchAction(@NotNull Project project, @NotNull List repositories, @NotNull HgRepository preselectedRepo) { @@ -105,25 +107,27 @@ public class HgBranchPopupActions { if (name == null) { return; } - try { - new HgBranchCreateCommand(myProject, myPreselectedRepo.getRoot(), name).execute(new HgCommandResultHandler() { - @Override - public void process(@Nullable HgCommandResult result) { - myPreselectedRepo.update(); - if (HgErrorUtil.hasErrorsInCommandExecution(result)) { - new HgCommandResultNotifier(myProject) - .notifyError(result, "Creation failed", "Branch creation [" + name + "] failed"); + for (final HgRepository repository : myRepositories) { + try { + new HgBranchCreateCommand(myProject, repository.getRoot(), name).execute(new HgCommandResultHandler() { + @Override + public void process(@Nullable HgCommandResult result) { + repository.update(); + if (HgErrorUtil.hasErrorsInCommandExecution(result)) { + new HgCommandResultNotifier(myProject) + .notifyError(result, "Creation failed", "Branch creation [" + name + "] failed"); + } } - } - }); - } - catch (HgCommandException exception) { - HgAbstractGlobalAction.handleException(myProject, "Can't create new branch: ", exception); + }); + } + catch (HgCommandException exception) { + HgAbstractGlobalAction.handleException(myProject, "Can't create new branch: ", exception); + } } } } - private static class HgNewBookmarkAction extends DumbAwareAction { + public static class HgNewBookmarkAction extends DumbAwareAction { @NotNull protected final List myRepositories; @NotNull protected Project myProject; @NotNull final HgRepository myPreselectedRepo; @@ -149,18 +153,20 @@ public class HgBranchPopupActions { final HgBookmarkDialog bookmarkDialog = new HgBookmarkDialog(myPreselectedRepo); bookmarkDialog.show(); if (bookmarkDialog.isOK()) { - try { - final String name = bookmarkDialog.getName(); - new HgBookmarkCommand(myProject, myPreselectedRepo.getRoot(), name).createBookmark(bookmarkDialog.isActive()); - } - catch (HgCommandException exception) { - HgAbstractGlobalAction.handleException(myProject, exception); + final String name = bookmarkDialog.getName(); + for (HgRepository repository : myRepositories) { + try { + new HgBookmarkCommand(myProject, repository.getRoot(), name).createBookmark(bookmarkDialog.isActive()); + } + catch (HgCommandException exception) { + HgAbstractGlobalAction.handleException(myProject, exception); + } } } } } - static private class HgShowUnnamedHeadsForCurrentBranchAction extends ActionGroup { + public static class HgShowUnnamedHeadsForCurrentBranchAction extends ActionGroup { @NotNull final Project myProject; @NotNull final HgRepository myRepository; @NotNull final String myCurrentBranchName; @@ -210,7 +216,7 @@ public class HgBranchPopupActions { public AnAction[] getChildren(@Nullable AnActionEvent e) { List branchHeadActions = new ArrayList(); for (Hash hash : myHeads) { - branchHeadActions.add(new HgCommonBranchActions(myProject, myRepository, hash.toShortString())); + branchHeadActions.add(new HgCommonBranchActions(myProject, Collections.singletonList(myRepository), hash.toShortString())); } return ContainerUtil.toArray(branchHeadActions, new AnAction[branchHeadActions.size()]); } @@ -232,29 +238,31 @@ public class HgBranchPopupActions { */ static class BookmarkActions extends HgCommonBranchActions { - BookmarkActions(@NotNull Project project, @NotNull HgRepository selectedRepository, @NotNull String branchName) { - super(project, selectedRepository, branchName); + BookmarkActions(@NotNull Project project, @NotNull List repositories, @NotNull String branchName) { + super(project, repositories, branchName); } @NotNull @Override public AnAction[] getChildren(@Nullable AnActionEvent e) { - return ArrayUtil.append(super.getChildren(e), new DeleteBookmarkAction(myProject, mySelectedRepository, myBranchName)); + return ArrayUtil.append(super.getChildren(e), new DeleteBookmarkAction(myProject, myRepositories, myBranchName)); } private static class DeleteBookmarkAction extends HgBranchAbstractAction { - DeleteBookmarkAction(@NotNull Project project, @NotNull HgRepository selectedRepository, @NotNull String branchName) { - super(project, "Delete", selectedRepository, branchName); + DeleteBookmarkAction(@NotNull Project project, @NotNull List repositories, @NotNull String branchName) { + super(project, "Delete", repositories, branchName); } @Override public void actionPerformed(AnActionEvent e) { - try { - new HgBookmarkCommand(myProject, mySelectedRepository.getRoot(), myBranchName).deleteBookmark(); - } - catch (HgCommandException exception) { - HgAbstractGlobalAction.handleException(myProject, exception); + for (HgRepository repository : myRepositories) { + try { + new HgBookmarkCommand(myProject, repository.getRoot(), myBranchName).deleteBookmark(); + } + catch (HgCommandException exception) { + HgAbstractGlobalAction.handleException(myProject, exception); + } } } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchUtil.java new file mode 100644 index 000000000000..9dbdd3ea7f65 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchUtil.java @@ -0,0 +1,77 @@ +/* + * 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 org.zmlx.hg4idea.branch; + +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcs.log.Hash; +import org.jetbrains.annotations.NotNull; +import org.zmlx.hg4idea.HgNameWithHashInfo; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.util.HgUtil; + +import java.util.*; + +public class HgBranchUtil { + + /** + * Only common hg heavy branches + */ + @NotNull + public static Collection getCommonBranches(@NotNull Collection repositories) { + Collection commonBranches = null; + for (HgRepository repository : repositories) { + Map> branchesWithHashes = repository.getBranches(); + Collection names = branchesWithHashes.keySet(); + if (commonBranches == null) { + commonBranches = names; + } + else { + commonBranches = ContainerUtil.intersection(commonBranches, names); + } + } + if (commonBranches != null) { + ArrayList common = new ArrayList(commonBranches); + Collections.sort(common); + return common; + } + else { + return Collections.emptyList(); + } + } + + @NotNull + public static Collection getCommonBookmarks(@NotNull Collection repositories) { + Collection commonBookmarkNames = null; + for (HgRepository repository : repositories) { + Collection bookmarksInfo = repository.getBookmarks(); + Collection names = HgUtil.getNamesWithoutHashes(bookmarksInfo); + if (commonBookmarkNames == null) { + commonBookmarkNames = names; + } + else { + commonBookmarkNames = ContainerUtil.intersection(commonBookmarkNames, names); + } + } + if (commonBookmarkNames != null) { + ArrayList common = new ArrayList(commonBookmarkNames); + Collections.sort(common); + return common; + } + else { + return Collections.emptyList(); + } + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchesAction.java similarity index 92% rename from plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java rename to plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchesAction.java index d799cde1705c..b078da12548f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchesAction.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgBranchesAction.java @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.zmlx.hg4idea.action; +package org.zmlx.hg4idea.branch; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.action.HgAbstractGlobalSingleRepoAction; import org.zmlx.hg4idea.repo.HgRepository; import java.util.Collection; diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgCommonBranchActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgCommonBranchActions.java new file mode 100644 index 000000000000..ecba99f7b532 --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgCommonBranchActions.java @@ -0,0 +1,141 @@ +/* + * 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 org.zmlx.hg4idea.branch; + +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.VcsNotifier; +import com.intellij.openapi.vcs.update.UpdatedFiles; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.zmlx.hg4idea.HgVcs; +import org.zmlx.hg4idea.HgVcsMessages; +import org.zmlx.hg4idea.action.HgAbstractGlobalAction; +import org.zmlx.hg4idea.action.HgCommandResultNotifier; +import org.zmlx.hg4idea.command.HgMergeCommand; +import org.zmlx.hg4idea.command.HgUpdateCommand; +import org.zmlx.hg4idea.execution.HgCommandResult; +import org.zmlx.hg4idea.provider.update.HgConflictResolver; +import org.zmlx.hg4idea.provider.update.HgHeadMerger; +import org.zmlx.hg4idea.repo.HgRepository; +import org.zmlx.hg4idea.util.HgErrorUtil; + +import java.util.List; + +public class HgCommonBranchActions extends ActionGroup { + + @NotNull protected final Project myProject; + @NotNull protected String myBranchName; + @NotNull List myRepositories; + + HgCommonBranchActions(@NotNull Project project, @NotNull List repositories, @NotNull String branchName) { + super("", true); + myProject = project; + myBranchName = branchName; + myRepositories = repositories; + getTemplatePresentation().setText(myBranchName, false); // no mnemonics + } + + @NotNull + @Override + public AnAction[] getChildren(@Nullable AnActionEvent e) { + return new AnAction[]{ + new UpdateAction(myProject, myRepositories, myBranchName), + new MergeAction(myProject, myRepositories, myBranchName) + }; + } + + private static class MergeAction extends HgBranchAbstractAction { + + public MergeAction(@NotNull Project project, + @NotNull List repositories, + @NotNull String branchName) { + super(project, "Merge", repositories, branchName); + } + + @Override + public void actionPerformed(AnActionEvent e) { + FileDocumentManager.getInstance().saveAllDocuments(); + final UpdatedFiles updatedFiles = UpdatedFiles.create(); + for (final HgRepository repository : myRepositories) { + final HgMergeCommand hgMergeCommand = new HgMergeCommand(myProject, repository.getRoot()); + hgMergeCommand.setRevision(myBranchName);//there is no difference between branch or revision or bookmark as parameter to merge, + // we need just a string + new Task.Backgroundable(myProject, "Merging changes...") { + @Override + public void run(@NotNull ProgressIndicator indicator) { + try { + new HgHeadMerger(myProject, hgMergeCommand) + .merge(repository.getRoot()); + new HgConflictResolver(myProject, updatedFiles).resolve(repository.getRoot()); + } + + catch (VcsException exception) { + assert myProject != null; // myProject couldn't be null, see annotation for Merge action + if (exception.isWarning()) { + VcsNotifier.getInstance(myProject).notifyWarning("Warning during merge", exception.getMessage()); + } + else { + VcsNotifier.getInstance(myProject).notifyError("Exception during merge", exception.getMessage()); + } + } + catch (Exception e1) { + HgAbstractGlobalAction.handleException(myProject, e1); + } + } + }.queue(); + } + } + } + + private static class UpdateAction extends HgBranchAbstractAction { + + public UpdateAction(@NotNull Project project, + @NotNull List repositories, + @NotNull String branchName) { + super(project, "Update", repositories, branchName); + } + + @Override + public void actionPerformed(AnActionEvent e) { + FileDocumentManager.getInstance().saveAllDocuments(); + for (HgRepository repo : myRepositories) { + final VirtualFile repository = repo.getRoot(); + final HgUpdateCommand hgUpdateCommand = new HgUpdateCommand(myProject, repository); + hgUpdateCommand.setBranch(myBranchName); + new Task.Backgroundable(myProject, HgVcsMessages.message("action.hg4idea.updateTo.description", myBranchName)) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + HgCommandResult result = hgUpdateCommand.execute(); + assert myProject != null; // myProject couldn't be null, see annotation for updateTo action + if (HgErrorUtil.hasErrorsInCommandExecution(result)) { + new HgCommandResultNotifier(myProject).notifyError(result, "", "Update failed"); + new HgConflictResolver(myProject).resolve(repository); + } + myProject.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(myProject, repository); + } + }.queue(); + } + } + } +} \ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgMultiRootBranchConfig.java b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgMultiRootBranchConfig.java new file mode 100644 index 000000000000..e762fb8992ab --- /dev/null +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/branch/HgMultiRootBranchConfig.java @@ -0,0 +1,50 @@ +/* + * 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 org.zmlx.hg4idea.branch; + +import com.intellij.dvcs.branch.DvcsMultiRootBranchConfig; +import org.jetbrains.annotations.NotNull; +import org.zmlx.hg4idea.repo.HgRepository; + +import java.util.Collection; + +public class HgMultiRootBranchConfig extends DvcsMultiRootBranchConfig { + + public HgMultiRootBranchConfig(@NotNull Collection repositories) { + super(repositories); + } + + @NotNull + @Override + public Collection getLocalBranchNames() { + return HgBranchUtil.getCommonBranches(myRepositories); + } + + @NotNull + Collection getBookmarkNames() { + return HgBranchUtil.getCommonBookmarks(myRepositories); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (HgRepository repository : myRepositories) { + sb.append(repository.getPresentableUrl()).append(":").append(repository.getCurrentBranchName()).append(":") + .append(repository.getState()); + } + return sb.toString(); + } +} diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java index bb865468e233..b28703930b6f 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/push/HgPushSupport.java @@ -64,7 +64,7 @@ public class HgPushSupport extends PushSupport
- + - + @@ -11,7 +11,7 @@ - + @@ -39,16 +39,43 @@ - + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + @@ -65,7 +92,7 @@ - + @@ -80,11 +107,6 @@ - - - - - diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java index 2aff9073d266..619536de0f88 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java @@ -12,14 +12,18 @@ // limitations under the License. package org.zmlx.hg4idea.ui; +import com.intellij.dvcs.branch.DvcsBranchSync; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.ui.components.JBCheckBox; import org.jetbrains.annotations.NotNull; import org.zmlx.hg4idea.HgProjectSettings; import org.zmlx.hg4idea.HgVcs; import org.zmlx.hg4idea.HgVcsMessages; +import org.zmlx.hg4idea.repo.HgRepositoryManager; import org.zmlx.hg4idea.util.HgUtil; import org.zmlx.hg4idea.util.HgVersion; @@ -36,6 +40,8 @@ public class HgConfigurationProjectPanel { private JCheckBox myIgnoredWhitespacesInAnnotationsCbx; private TextFieldWithBrowseButton myPathSelector; private JButton myTestButton; + private JBCheckBox mySyncBranchControl; + private JPanel myRepositorySettingsPanel; private final HgVcs myVcs; public HgConfigurationProjectPanel(@NotNull HgProjectSettings projectSettings, @NotNull Project project) { @@ -58,12 +64,15 @@ public class HgConfigurationProjectPanel { ); } }); + final HgRepositoryManager repositoryManager = ServiceManager.getService(project, HgRepositoryManager.class); + myRepositorySettingsPanel.setVisible(repositoryManager != null && repositoryManager.moreThanOneRoot()); } public boolean isModified() { boolean executableModified = !getCurrentPath().equals(myProjectSettings.getHgExecutable()); return executableModified || myCheckIncomingOutgoingCbx.isSelected() != myProjectSettings.isCheckIncomingOutgoing() || + ((myProjectSettings.getSyncSetting() == DvcsBranchSync.SYNC) != mySyncBranchControl.isSelected()) || myIgnoredWhitespacesInAnnotationsCbx.isSelected() != myProjectSettings.isWhitespacesIgnoredInAnnotations(); } @@ -71,6 +80,7 @@ public class HgConfigurationProjectPanel { myProjectSettings.setCheckIncomingOutgoing(myCheckIncomingOutgoingCbx.isSelected()); myProjectSettings.setIgnoreWhitespacesInAnnotations(myIgnoredWhitespacesInAnnotationsCbx.isSelected()); myProjectSettings.setHgExecutable(getCurrentPath()); + myProjectSettings.setSyncSetting(mySyncBranchControl.isSelected() ? DvcsBranchSync.SYNC : DvcsBranchSync.DONT); myVcs.checkVersion(); } @@ -82,6 +92,7 @@ public class HgConfigurationProjectPanel { myCheckIncomingOutgoingCbx.setSelected(myProjectSettings.isCheckIncomingOutgoing()); myIgnoredWhitespacesInAnnotationsCbx.setSelected(myProjectSettings.isWhitespacesIgnoredInAnnotations()); myPathSelector.setText(myProjectSettings.getGlobalSettings().getHgExecutable()); + mySyncBranchControl.setSelected(myProjectSettings.getSyncSetting() == DvcsBranchSync.SYNC); } public JPanel getPanel() { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java index d055ca247129..fcf275f70703 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java @@ -585,16 +585,7 @@ public abstract class HgUtil { if (state != HgRepository.State.NORMAL) { branchText += state.toString() + " "; } - return branchText + getActiveBranchName(repository); - } - - @NotNull - public static String getActiveBranchName(@NotNull HgRepository repository) { - String branchOrBookMarkName = repository.getCurrentBookmark(); - if (StringUtil.isEmptyOrSpaces(branchOrBookMarkName)) { - branchOrBookMarkName = repository.getCurrentBranch(); - } - return branchOrBookMarkName; + return branchText + repository.getCurrentBranchName(); } @NotNull diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/AssertProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/AssertProcessor.java index da703fd98221..a58b68903563 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/AssertProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/AssertProcessor.java @@ -60,7 +60,7 @@ public class AssertProcessor { if (res) { // hide the helper field - wrapper.getHideMembers().add(key); + wrapper.getHiddenMembers().add(key); } } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java index 4552b1d309e0..3807d2e80a27 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java @@ -114,7 +114,7 @@ public class ClassReference14Processor { if (!setFound.isEmpty()) { for (ClassWrapper wrp : setFound) { StructMethod mt = mapClassMeths.get(wrp).methodStruct; - wrp.getHideMembers().add(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor())); + wrp.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor())); } } } @@ -276,7 +276,7 @@ public class ClassReference14Processor { invexpr.getStringDescriptor().equals(meth.methodStruct.getDescriptor())) { if (invexpr.getLstParameters().get(0).type == Exprent.EXPRENT_CONST) { - wrapper.getHideMembers() + wrapper.getHiddenMembers() .add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); // hide synthetic field return ((ConstExprent)invexpr.getLstParameters().get(0)).getValue().toString(); } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java index c6dc7a415f64..ffc57d830dbd 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -239,7 +239,7 @@ public class ClassWriter { if ((!isSynthetic || !DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC)) && (!isBridge || !DecompilerContext.getOption(IFernflowerPreferences.REMOVE_BRIDGE)) && - !wrapper.getHideMembers().contains(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()))) { + !wrapper.getHiddenMembers().contains(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()))) { if (!mthidden && (!firstmt || node.type != ClassNode.CLASS_ANONYMOUS)) { bufstrwriter.write(DecompilerContext.getNewLineSeparator()); firstmt = false; @@ -260,7 +260,7 @@ public class ClassWriter { // fields for (StructField fd : cl.getFields()) { boolean hide = fd.isSynthetic() && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) || - wrapper.getHideMembers().contains(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); + wrapper.getHiddenMembers().contains(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); if (!hide) { boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); if (isEnum) { @@ -308,7 +308,7 @@ public class ClassWriter { StructClass innerCl = inner.classStruct; boolean isSynthetic = (inner.access & CodeConstants.ACC_SYNTHETIC) != 0 || innerCl.isSynthetic(); boolean hide = isSynthetic && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) || - wrapper.getHideMembers().contains(innerCl.qualifiedName); + wrapper.getHiddenMembers().contains(innerCl.qualifiedName); if (!hide) { writer.write(DecompilerContext.getNewLineSeparator()); classToJava(inner, writer, indent + 1); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java index a16e4e0dc590..034efb180776 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java @@ -235,7 +235,7 @@ public class ClassesProcessor { } - public void writeClass(StructContext context, StructClass cl, BufferedWriter outwriter) throws IOException { + public void writeClass(StructClass cl, BufferedWriter writer) throws IOException { ClassNode root = mapRootClasses.get(cl.qualifiedName); if (root.type != ClassNode.CLASS_ROOT) { @@ -270,20 +270,20 @@ public class ClassesProcessor { int index = cl.qualifiedName.lastIndexOf("/"); if (index >= 0) { String packageName = cl.qualifiedName.substring(0, index).replace('/', '.'); - outwriter.write("package "); - outwriter.write(packageName); - outwriter.write(";"); - outwriter.write(DecompilerContext.getNewLineSeparator()); - outwriter.write(DecompilerContext.getNewLineSeparator()); + writer.write("package "); + writer.write(packageName); + writer.write(";"); + writer.write(DecompilerContext.getNewLineSeparator()); + writer.write(DecompilerContext.getNewLineSeparator()); } DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, root); - DecompilerContext.getImportCollector().writeImports(outwriter); - outwriter.write(DecompilerContext.getNewLineSeparator()); + DecompilerContext.getImportCollector().writeImports(writer); + writer.write(DecompilerContext.getNewLineSeparator()); - outwriter.write(strwriter.toString()); - outwriter.flush(); + writer.write(strwriter.toString()); + writer.flush(); } finally { destroyWrappers(root); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/EnumProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/EnumProcessor.java index fcdeaf164520..be408e8bbc3b 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/EnumProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/EnumProcessor.java @@ -15,97 +15,58 @@ */ package org.jetbrains.java.decompiler.main; -import org.jetbrains.java.decompiler.code.CodeConstants; -import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.rels.ClassWrapper; import org.jetbrains.java.decompiler.main.rels.MethodWrapper; import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.InvocationExprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.NewExprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent; import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar; import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructField; import org.jetbrains.java.decompiler.struct.StructMethod; -import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; -import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.util.InterpreterUtil; public class EnumProcessor { public static void clearEnum(ClassWrapper wrapper) { - StructClass cl = wrapper.getClassStruct(); - // hide values() and valueOf() - for (StructMethod meth : cl.getMethods()) { - - String name = meth.getName(); - int flag = 0; + // hide values/valueOf methods and super() invocations + for (MethodWrapper method : wrapper.getMethods()) { + StructMethod mt = method.methodStruct; + String name = mt.getName(); + String descriptor = mt.getDescriptor(); if ("values".equals(name)) { - flag = 1; + if (descriptor.equals("()[L" + cl.qualifiedName + ";")) { + wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(name, descriptor)); + } } else if ("valueOf".equals(name)) { - flag = 2; - } - - if (flag > 0) { - String[] arr = meth.getDescriptor().split("[()]"); - String par = arr[1]; - - if ((flag == 1 && par.length() == 0) || - flag == 2 && "Ljava/lang/String;".equals(par)) { - wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(name, meth.getDescriptor())); + if (descriptor.equals("(Ljava/lang/String;)L" + cl.qualifiedName + ";")) { + wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(name, descriptor)); } } - } - - // hide all super invocations - for (MethodWrapper meth : wrapper.getMethods()) { - if ("".equals(meth.methodStruct.getName())) { - Statement firstdata = findFirstData(meth.root); - if (firstdata == null || firstdata.getExprents().isEmpty()) { - return; - } - - Exprent exprent = firstdata.getExprents().get(0); - if (exprent.type == Exprent.EXPRENT_INVOCATION) { - InvocationExprent invexpr = (InvocationExprent)exprent; - if (isInvocationSuperConstructor(invexpr, meth, wrapper)) { - firstdata.getExprents().remove(0); + else if ("".equals(name)) { + Statement firstData = findFirstData(method.root); + if (firstData != null && !firstData.getExprents().isEmpty()) { + Exprent exprent = firstData.getExprents().get(0); + if (exprent.type == Exprent.EXPRENT_INVOCATION) { + InvocationExprent invexpr = (InvocationExprent)exprent; + if (isInvocationSuperConstructor(invexpr, method, wrapper)) { + firstData.getExprents().remove(0); + } } } } } - // hide dummy synthetic fields of enum constants + // hide synthetic fields of enum and it's constants for (StructField fd : cl.getFields()) { - if (fd.hasModifier(CodeConstants.ACC_ENUM)) { - Exprent initializer = - wrapper.getStaticFieldInitializers().getWithKey(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); - if (initializer != null && initializer.type == Exprent.EXPRENT_NEW) { - NewExprent nexpr = (NewExprent)initializer; - if (nexpr.isAnonymous()) { - ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(nexpr.getNewtype().value); - hideDummyFieldInConstant(child.wrapper); - } - } - } - } - } - - private static void hideDummyFieldInConstant(ClassWrapper wrapper) { - StructClass cl = wrapper.getClassStruct(); - for (StructField fd : cl.getFields()) { - if (fd.isSynthetic()) { - FieldDescriptor descr = FieldDescriptor.parseDescriptor(fd.getDescriptor()); - VarType ret = descr.type; - - if (ret.type == CodeConstants.TYPE_OBJECT && ret.arraydim == 1 && cl.qualifiedName.equals(ret.value)) { - wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); - } + String descriptor = fd.getDescriptor(); + if (fd.isSynthetic() && descriptor.equals("[L" + cl.qualifiedName + ";")) { + wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), descriptor)); } } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/Fernflower.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/Fernflower.java index 6d60f6ebf426..67596be00278 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/Fernflower.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/Fernflower.java @@ -28,81 +28,66 @@ import org.jetbrains.java.decompiler.struct.lazy.LazyLoader; import java.io.BufferedWriter; import java.io.StringWriter; -import java.util.HashMap; +import java.util.Map; public class Fernflower implements IDecompiledData { - public static final String version = "v0.8.4"; - - private StructContext structcontext; - - private ClassesProcessor clprocessor; - - public Fernflower(IBytecodeProvider provider, IDecompilatSaver saver, HashMap propertiesCustom) { - - structcontext = new StructContext(saver, this, new LazyLoader(provider)); + private StructContext structContext; + private ClassesProcessor classesProcessor; + public Fernflower(IBytecodeProvider provider, IDecompilatSaver saver, Map propertiesCustom) { + structContext = new StructContext(saver, this, new LazyLoader(provider)); DecompilerContext.initContext(propertiesCustom); DecompilerContext.setCounterContainer(new CounterContainer()); } public void decompileContext() { - if (DecompilerContext.getOption(IFernflowerPreferences.RENAME_ENTITIES)) { - new IdentifierConverter().rename(structcontext); + new IdentifierConverter().rename(structContext); } - clprocessor = new ClassesProcessor(structcontext); + classesProcessor = new ClassesProcessor(structContext); - DecompilerContext.setClassProcessor(clprocessor); - DecompilerContext.setStructContext(structcontext); + DecompilerContext.setClassProcessor(classesProcessor); + DecompilerContext.setStructContext(structContext); - structcontext.saveContext(); + structContext.saveContext(); } public void clearContext() { DecompilerContext.setCurrentContext(null); } - public String getClassEntryName(StructClass cl, String entryname) { - - ClassNode node = clprocessor.getMapRootClasses().get(cl.qualifiedName); + public String getClassEntryName(StructClass cl, String entryName) { + ClassNode node = classesProcessor.getMapRootClasses().get(cl.qualifiedName); if (node.type != ClassNode.CLASS_ROOT) { return null; } else { if (DecompilerContext.getOption(IFernflowerPreferences.RENAME_ENTITIES)) { String simple_classname = cl.qualifiedName.substring(cl.qualifiedName.lastIndexOf('/') + 1); - return entryname.substring(0, entryname.lastIndexOf('/') + 1) + simple_classname + ".java"; + return entryName.substring(0, entryName.lastIndexOf('/') + 1) + simple_classname + ".java"; } else { - return entryname.substring(0, entryname.lastIndexOf(".class")) + ".java"; + return entryName.substring(0, entryName.lastIndexOf(".class")) + ".java"; } } } - public StructContext getStructcontext() { - return structcontext; + public StructContext getStructContext() { + return structContext; } public String getClassContent(StructClass cl) { - - String res = null; - try { - StringWriter strwriter = new StringWriter(); - clprocessor.writeClass(structcontext, cl, new BufferedWriter(strwriter)); - - res = strwriter.toString(); - } - catch (ThreadDeath ex) { - throw ex; + StringWriter writer = new StringWriter(); + classesProcessor.writeClass(cl, new BufferedWriter(writer)); + return writer.toString(); } catch (Throwable ex) { DecompilerContext.getLogger().writeMessage("Class " + cl.qualifiedName + " couldn't be fully decompiled.", ex); + return null; } - - return res; } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java index bfb4e70eec49..d499324dab9c 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java @@ -128,7 +128,7 @@ public class ConsoleDecompiler implements IBytecodeProvider, IDecompilatSaver { } public void addSpace(File file, boolean isOwn) throws IOException { - fernflower.getStructcontext().addSpace(file, isOwn); + fernflower.getStructContext().addSpace(file, isOwn); } public void decompileContext(File root) { @@ -213,7 +213,7 @@ public class ConsoleDecompiler implements IBytecodeProvider, IDecompilatSaver { ZipOutputStream out = mapArchiveStreams.get(filename); out.putNextEntry(new ZipEntry(entryName)); - InterpreterUtil.copyInputStream(in, out); + InterpreterUtil.copyStream(in, out); in.close(); } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/IdeDecompiler.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/IdeDecompiler.java index dab59e973bfe..212a8bd4bc71 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/IdeDecompiler.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/decompiler/IdeDecompiler.java @@ -40,7 +40,7 @@ public class IdeDecompiler { } public void addSpace(File file, boolean isOwn) throws IOException { - fernflower.getStructcontext().addSpace(file, isOwn); + fernflower.getStructContext().addSpace(file, isOwn); } public void decompileContext() { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java index 4ef8ba9f8d48..c942bad4961b 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java @@ -15,6 +15,8 @@ */ package org.jetbrains.java.decompiler.main.extern; +import org.jetbrains.java.decompiler.util.InterpreterUtil; + import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -75,10 +77,9 @@ public interface IFernflowerPreferences { put(IDEA_NOT_NULL_ANNOTATION, "1"); put(LAMBDA_TO_ANONYMOUS_CLASS, "0"); - boolean win = System.getProperty("os.name", "").startsWith("Windows"); put(MAX_PROCESSING_METHOD, "0"); put(RENAME_ENTITIES, "0"); - put(NEW_LINE_SEPARATOR, (win ? "0" : "1")); + put(NEW_LINE_SEPARATOR, (InterpreterUtil.IS_WINDOWS ? "0" : "1")); put(INDENT_STRING, " "); }}); } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java index cbaf227d98f2..ae251b9473ec 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java @@ -36,17 +36,14 @@ import org.jetbrains.java.decompiler.util.VBStyleCollection; import java.io.IOException; import java.util.HashSet; +import java.util.Set; public class ClassWrapper { private StructClass classStruct; - - private HashSet hideMembers = new HashSet(); - + private Set hiddenMembers = new HashSet(); private VBStyleCollection staticFieldInitializers = new VBStyleCollection(); - private VBStyleCollection dynamicFieldInitializers = new VBStyleCollection(); - private VBStyleCollection methods = new VBStyleCollection(); @@ -54,7 +51,6 @@ public class ClassWrapper { this.classStruct = classStruct; } - @SuppressWarnings("deprecation") public void init() throws IOException { DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS, classStruct); @@ -111,7 +107,7 @@ public class ClassWrapper { if (System.currentTimeMillis() >= stopAt) { String message = "Processing time limit exceeded for method " + mt.getName() + ", execution interrupted."; DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.ERROR); - mtthread.stop(); + killThread(mtthread); isError = true; break; } @@ -180,6 +176,11 @@ public class ClassWrapper { DecompilerContext.getLogger().endClass(); } + @SuppressWarnings("deprecation") + private static void killThread(Thread thread) { + thread.stop(); + } + public MethodWrapper getMethodWrapper(String name, String descriptor) { return methods.getWithKey(InterpreterUtil.makeUniqueKey(name, descriptor)); } @@ -192,8 +193,8 @@ public class ClassWrapper { return methods; } - public HashSet getHideMembers() { - return hideMembers; + public Set getHiddenMembers() { + return hiddenMembers; } public VBStyleCollection getStaticFieldInitializers() { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java index 003bdc21e9cb..3757d7eb1991 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java @@ -50,7 +50,7 @@ public class NestedClassProcessor { if (node.type == ClassNode.CLASS_LAMBDA && !node.lambda_information.is_method_reference) { ClassNode node_content = DecompilerContext.getClassProcessor().getMapRootClasses().get(node.classStruct.qualifiedName); if (node_content != null && node_content.wrapper != null) { - node_content.wrapper.getHideMembers().add(node.lambda_information.content_method_key); + node_content.wrapper.getHiddenMembers().add(node.lambda_information.content_method_key); } } @@ -528,7 +528,7 @@ public class NestedClassProcessor { // hide synthetic field if (clnode == child) { // fields higher up the chain were already handled with their classes StructField fd = child.classStruct.getFields().getWithKey(entr.getKey()); - child.wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); + child.wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); } } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java index f61de8585d62..7e5eaa54326a 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java @@ -440,7 +440,7 @@ public class NestedMemberAccess { } } if (hide) { - node.wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(invexpr.getName(), invexpr.getStringDescriptor())); + node.wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(invexpr.getName(), invexpr.getStringDescriptor())); } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java index 6c6b1f3171f0..8ff9fe5a448a 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java @@ -20,7 +20,6 @@ import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; -import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructField; import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.util.InterpreterUtil; @@ -105,26 +104,33 @@ public class AssignmentExprent extends Exprent { } public String toJava(int indent) { - VarType leftType = left.getExprType(); VarType rightType = right.getExprType(); - boolean fieldInStatInit = false; + boolean fieldInClassInit = false, hiddenField = false; if (left.type == Exprent.EXPRENT_FIELD) { // first assignment to a final field. Field name without "this" in front of it FieldExprent field = (FieldExprent)left; ClassNode node = ((ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE)); if (node != null) { - StructClass cl = node.classStruct; - StructField fd = cl.getField(field.getName(), field.getDescriptor().descriptorString); - if (fd != null && field.isStatic() && fd.hasModifier(CodeConstants.ACC_FINAL)) { - fieldInStatInit = true; + StructField fd = node.classStruct.getField(field.getName(), field.getDescriptor().descriptorString); + if (fd != null) { + if (field.isStatic() && fd.hasModifier(CodeConstants.ACC_FINAL)) { + fieldInClassInit = true; + } + if (node.wrapper.getHiddenMembers().contains(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor()))) { + hiddenField = true; + } } } } + if (hiddenField) { + return ""; + } + StringBuilder buffer = new StringBuilder(); - if (fieldInStatInit) { + if (fieldInClassInit) { buffer.append(((FieldExprent)left).getName()); } else { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java index 89e11c0cb1d1..cc4e4bdbfe4c 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/util/InterpreterUtil.java @@ -25,6 +25,10 @@ import java.util.HashSet; import java.util.List; public class InterpreterUtil { + public static final boolean IS_WINDOWS = System.getProperty("os.name", "").startsWith("Windows"); + + private static final int CHANNEL_WINDOW_SIZE = IS_WINDOWS ? 64 * 1024 * 1024 - (32 * 1024) : 64 * 1024 * 1024; // magic number for Windows + private static final int BUFFER_SIZE = 16* 1024; public static void copyFile(File in, File out) throws IOException { FileInputStream inStream = new FileInputStream(in); @@ -33,12 +37,9 @@ public class InterpreterUtil { try { FileChannel inChannel = inStream.getChannel(); FileChannel outChannel = outStream.getChannel(); - // magic number for Windows, 64Mb - 32Kb) - int maxCount = (64 * 1024 * 1024) - (32 * 1024); - long size = inChannel.size(); - long position = 0; + long size = inChannel.size(), position = 0; while (position < size) { - position += inChannel.transferTo(position, maxCount, outChannel); + position += inChannel.transferTo(position, CHANNEL_WINDOW_SIZE, outChannel); } } finally { @@ -50,11 +51,9 @@ public class InterpreterUtil { } } - public static void copyInputStream(InputStream in, OutputStream out) throws IOException { - - byte[] buffer = new byte[1024]; + public static void copyStream(InputStream in, OutputStream out) throws IOException { + byte[] buffer = new byte[BUFFER_SIZE]; int len; - while ((len = in.read(buffer)) >= 0) { out.write(buffer, 0, len); } @@ -69,9 +68,7 @@ public class InterpreterUtil { return buf.toString(); } - public static boolean equalSets(Collection c1, Collection c2) { - if (c1 == null) { return c2 == null; } @@ -93,7 +90,6 @@ public class InterpreterUtil { } public static boolean equalObjectArrays(Object[] first, Object[] second) { - if (first == null || second == null) { return equalObjects(first, second); } @@ -113,12 +109,11 @@ public class InterpreterUtil { } public static boolean equalLists(List first, List second) { - if (first == null) { return second == null; } else if (second == null) { - return first == null; + return false; } if (first.size() == second.size()) { diff --git a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java index 02fb6123aa4c..f6146c972d8a 100644 --- a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -65,7 +65,7 @@ public class SingleClassesTest { @Test public void testMethodParameters() { doTest("TestMethodParameters"); } @Test public void testCodeConstructs() { doTest("TestCodeConstructs"); } @Test public void testConstants() { doTest("TestConstants"); } - //@Test public void testEnum() { doTest("TestEnum"); } + @Test public void testEnum() { doTest("TestEnum"); } private void doTest(final String testName) { try { diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GridCaptionPanel.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GridCaptionPanel.java index 77d3104abccc..99a982f5acd3 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GridCaptionPanel.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GridCaptionPanel.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,7 +20,10 @@ import com.intellij.ide.DeleteProvider; import com.intellij.ide.dnd.*; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.colors.EditorColors; +import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.util.Pair; +import com.intellij.ui.JBColor; import com.intellij.ui.LightColors; import com.intellij.uiDesigner.CaptionSelection; import com.intellij.uiDesigner.FormEditingUtil; @@ -33,7 +36,9 @@ import com.intellij.uiDesigner.radComponents.RadContainer; import com.intellij.uiDesigner.radComponents.RadRootContainer; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; +import com.intellij.util.NotNullProducer; import com.intellij.util.ui.PlatformColors; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -72,7 +77,7 @@ public class GridCaptionPanel extends JPanel implements ComponentSelectionListen myEditor.fireSelectedComponentChanged(); } }); - setBackground(Color.LIGHT_GRAY); + setBackground(getGutterColor()); editor.addComponentSelectionListener(this); final MyMouseListener listener = new MyMouseListener(); @@ -101,6 +106,17 @@ public class GridCaptionPanel extends JPanel implements ComponentSelectionListen }); } + public static JBColor getGutterColor() { + return new JBColor(new NotNullProducer() { + @NotNull + @Override + public Color produce() { + Color color = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.GUTTER_BACKGROUND); + return color == null ? UIUtil.getPanelBackground() : color; + } + }); + } + public RadContainer getSelectedContainer() { // when the selected component changes, and we have focus, PropertyInspector asks us about our container and selection. // PropertyInspector's selection changed listener can be called before our own listener, so we need to update ourselves diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java index dbbc27655f4e..96969998edf4 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/GuiEditor.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. @@ -27,6 +27,7 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.undo.UndoManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -61,7 +62,7 @@ import com.intellij.uiDesigner.radComponents.RadContainer; import com.intellij.uiDesigner.radComponents.RadRootContainer; import com.intellij.uiDesigner.radComponents.RadTabbedPane; import com.intellij.util.Alarm; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.NotNullProducer; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -288,7 +289,7 @@ public final class GuiEditor extends JPanel implements DataProvider, ModuleProvi readFromFile(false); JPanel panel = new JPanel(new GridBagLayout()); - panel.setBackground(Color.LIGHT_GRAY); + panel.setBackground(GridCaptionPanel.getGutterColor()); myHorzCaptionPanel = new GridCaptionPanel(this, false); myVertCaptionPanel = new GridCaptionPanel(this, true); @@ -311,7 +312,13 @@ public final class GuiEditor extends JPanel implements DataProvider, ModuleProvi gbc.weighty = 1.0; myScrollPane = ScrollPaneFactory.createScrollPane(myLayeredPane); - myScrollPane.setBackground(new JBColor(Color.WHITE, UIUtil.getListBackground())); + myScrollPane.setBackground(new JBColor(new NotNullProducer() { + @NotNull + @Override + public Color produce() { + return EditorColorsManager.getInstance().getGlobalScheme().getDefaultBackground(); + } + })); panel.add(myScrollPane, gbc); myHorzCaptionPanel.attachToScrollPane(myScrollPane); myVertCaptionPanel.attachToScrollPane(myScrollPane); diff --git a/python/edu/build/pycharm_edu_build.gant b/python/edu/build/pycharm_edu_build.gant index 28d829e68b34..b1fbedd83483 100644 --- a/python/edu/build/pycharm_edu_build.gant +++ b/python/edu/build/pycharm_edu_build.gant @@ -405,7 +405,7 @@ private layoutMac(Map _args, String target) { args.icns = "$pythonCommunityHome/resources/PyCharmCore.icns" args.bundleIdentifier = "com.jetbrains.pycharm" args.platform_prefix = "PyCharmEdu" - args.help_id = "PY" + args.help_id = "PE" args."idea.properties.path" = "${paths.distAll}/bin/idea.properties" args."idea.properties" = ["idea.no.jre.check": true, "ide.mac.useNativeClipboard": "false"]; layoutMacApp(target, ch, args) diff --git a/python/helpers/pycharm/_bdd_utils.py b/python/helpers/pycharm/_bdd_utils.py index eea1bebf1654..9eb90681e127 100644 --- a/python/helpers/pycharm/_bdd_utils.py +++ b/python/helpers/pycharm/_bdd_utils.py @@ -29,19 +29,27 @@ def fix_win_drive(feature_path): os.chdir(feature_disk) -def get_path_by_args(arguments): +def get_path_by_env(environment): """ - :type arguments list - :param arguments: arguments (sys.argv) - :return: tuple (base_dir, what_to_run) where dir is current or first argument from argv, checking it exists - :rtype tuple of str + :type environment dict + :param environment: os.environment (files and folders should be separated with | and passed to PY_STUFF_TO_RUN) + :return: tuple (base_dir, what_to_run(list of feature files or folders))) where dir is current or first argument from env, checking it exists + :rtype tuple of (str, iterable) """ - what_to_run = arguments[1] if len(arguments) > 1 else "." - base_dir = what_to_run - assert os.path.exists(what_to_run), "{} does not exist".format(what_to_run) + if "PY_STUFF_TO_RUN" not in environment: + what_to_run = ["."] + else: + what_to_run = str(environment["PY_STUFF_TO_RUN"]).split("|") - if os.path.isfile(what_to_run): - base_dir = os.path.dirname(what_to_run) # User may point to the file directly + if not what_to_run: + what_to_run = ["."] + + for path in what_to_run: + assert os.path.exists(path), "{} does not exist".format(path) + + base_dir = what_to_run[0] + if os.path.isfile(what_to_run[0]): + base_dir = os.path.dirname(what_to_run[0]) # User may point to the file directly return base_dir, what_to_run diff --git a/python/helpers/pycharm/behave_runner.py b/python/helpers/pycharm/behave_runner.py index 2ec649ea7c1d..51171530ddb4 100644 --- a/python/helpers/pycharm/behave_runner.py +++ b/python/helpers/pycharm/behave_runner.py @@ -1,13 +1,14 @@ # coding=utf-8 """ Behave BDD runner. -*FIRST* param now: folder to search "features" for. -Each "features" folder should have features and "steps" subdir. +See _bdd_utils#get_path_by_env for information how to pass list of features here. +Each feature could be file, folder with feature files or folder with "features" subfolder Other args are tag expressionsin format (--tags=.. --tags=..). See https://pythonhosted.org/behave/behave.html#tag-expression """ import functools +import glob import sys import os import traceback @@ -236,12 +237,14 @@ if __name__ == "__main__": my_config.reporters = [] # To prevent summary to stdout my_config.stdout_capture = False # For test output my_config.stderr_capture = False # For test output - (base_dir, what_to_run) = _bdd_utils.get_path_by_args(sys.argv) - if not my_config.paths: # No path provided, trying to load dit manually - if os.path.isfile(what_to_run): # File is provided, load it - my_config.paths = [what_to_run] - else: # Dir is provided, find subdirs ro run - my_config.paths = _get_dirs_to_run(base_dir) + (base_dir, what_to_run) = _bdd_utils.get_path_by_env(os.environ) + features = set() + for feature in what_to_run: + if os.path.isfile(feature) or glob.glob(os.path.join(feature, "*.feature")): # File of folder with "features" provided, load it + features.add(feature) + elif os.path.isdir(feature): + features |= set(_get_dirs_to_run(feature)) # Find "features" subfolder + my_config.paths = list(features) _BehaveRunner(my_config, base_dir).run() diff --git a/python/helpers/pycharm/lettuce_runner.py b/python/helpers/pycharm/lettuce_runner.py index f0a4b5dbb873..6c4dbb7028a6 100644 --- a/python/helpers/pycharm/lettuce_runner.py +++ b/python/helpers/pycharm/lettuce_runner.py @@ -4,6 +4,7 @@ BDD lettuce framework runner TODO: Support other params (like tags) as well. Supports only 1 param now: folder to search "features" for. """ +import os import _bdd_utils __author__ = 'Ilya.Kazakevich' @@ -108,6 +109,8 @@ class _LettuceRunner(_bdd_utils.BddRunner): if __name__ == "__main__": - (base_dir, what_to_run) = _bdd_utils.get_path_by_args(sys.argv) - _bdd_utils.fix_win_drive(what_to_run) - _LettuceRunner(base_dir, what_to_run).run() \ No newline at end of file + (base_dir, what_to_run) = _bdd_utils.get_path_by_env(os.environ) + if len(what_to_run) > 1: + raise Exception("Lettuce can't run more than one file now") + _bdd_utils.fix_win_drive(what_to_run[0]) + _LettuceRunner(base_dir, what_to_run[0]).run() \ No newline at end of file diff --git a/resources/src/idea/JavaActions.xml b/resources/src/idea/JavaActions.xml index 81a791f42208..31f6d9ad84f4 100644 --- a/resources/src/idea/JavaActions.xml +++ b/resources/src/idea/JavaActions.xml @@ -153,7 +153,6 @@ - @@ -178,6 +177,9 @@ + + + diff --git a/xml/relaxng/src/org/intellij/html/RelaxedHtmlFromRngElementDescriptor.java b/xml/relaxng/src/org/intellij/html/RelaxedHtmlFromRngElementDescriptor.java index 08ada22129d9..b287e6b50777 100644 --- a/xml/relaxng/src/org/intellij/html/RelaxedHtmlFromRngElementDescriptor.java +++ b/xml/relaxng/src/org/intellij/html/RelaxedHtmlFromRngElementDescriptor.java @@ -69,6 +69,9 @@ public class RelaxedHtmlFromRngElementDescriptor implements XmlElementDescriptor @Override public XmlAttributeDescriptor getAttributeDescriptor(XmlAttribute attribute) { + XmlAttributeDescriptor descriptor = myDelegate.getAttributeDescriptor(attribute); + if (descriptor != null) return descriptor; + return getAttributeDescriptor(attribute.getName(), attribute.getParent()); } diff --git a/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc b/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc index fe154b8f57bf..095868dee70a 100644 --- a/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc +++ b/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc @@ -1,7 +1,7 @@ namespace svg = "http://www.w3.org/2000/svg" namespace math = "http://www.w3.org/1998/Math/MathML" -include "svg11/svg11-tiny-inc.rnc" +include "svg11/svg11-inc.rnc" include "mml3/mathml3-inc.rnc" common.elem.phrasing |= svg diff --git a/xml/relaxng/src/resources/html5-schema/xhtml5-svg-mathml.rnc b/xml/relaxng/src/resources/html5-schema/xhtml5-svg-mathml.rnc index 74f188644741..98d6fbd597e4 100644 --- a/xml/relaxng/src/resources/html5-schema/xhtml5-svg-mathml.rnc +++ b/xml/relaxng/src/resources/html5-schema/xhtml5-svg-mathml.rnc @@ -2,7 +2,7 @@ namespace svg = "http://www.w3.org/2000/svg" namespace math = "http://www.w3.org/1998/Math/MathML" namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" -include "svg11/svg11-tiny-inc.rnc" +include "svg11/svg11-inc.rnc" include "inkscape/inkscape.rnc" include "mml3/mathml3-inc.rnc" include "rdf/rdf.rnc" diff --git a/xml/relaxng/src/resources/patches/0007_html5_svg_tiny.patch b/xml/relaxng/src/resources/patches/0007_html5_svg_tiny.patch deleted file mode 100644 index 6a3cc10cc8e2..000000000000 --- a/xml/relaxng/src/resources/patches/0007_html5_svg_tiny.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- /Users/denofevil/Code/sandbox/checker/validator/schema/html5-svg-mathml.rnc 2014-01-24 12:18:54.000000000 +0400 -+++ html5-svg-mathml.rnc 2014-01-25 15:32:10.000000000 +0400 -@@ -1,7 +1,7 @@ - namespace svg = "http://www.w3.org/2000/svg" - namespace math = "http://www.w3.org/1998/Math/MathML" - --include "svg11/svg11-inc.rnc" -+include "svg11/svg11-tiny-inc.rnc" - include "mml3/mathml3-inc.rnc" - - common.elem.phrasing |= svg diff --git a/xml/relaxng/src/resources/patches/0008_xhtml5_svg_tiny.patch b/xml/relaxng/src/resources/patches/0008_xhtml5_svg_tiny.patch deleted file mode 100644 index 773c8969c177..000000000000 --- a/xml/relaxng/src/resources/patches/0008_xhtml5_svg_tiny.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- /Users/denofevil/Code/sandbox/checker/validator/schema/xhtml5-svg-mathml.rnc 2014-01-24 12:18:54.000000000 +0400 -+++ xhtml5-svg-mathml.rnc 2014-01-25 15:50:41.000000000 +0400 -@@ -2,7 +2,7 @@ - namespace math = "http://www.w3.org/1998/Math/MathML" - namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" - --include "svg11/svg11-inc.rnc" -+include "svg11/svg11-tiny-inc.rnc" - include "inkscape/inkscape.rnc" - include "mml3/mathml3-inc.rnc" - include "rdf/rdf.rnc" diff --git a/xml/xml-psi-impl/resources/standardSchemas/xlink.dtd b/xml/xml-psi-impl/resources/standardSchemas/xlink.dtd new file mode 100644 index 000000000000..1a8f153e55db --- /dev/null +++ b/xml/xml-psi-impl/resources/standardSchemas/xlink.dtd @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml/xml-psi-impl/src/com/intellij/javaee/InternalResourceProvider.java b/xml/xml-psi-impl/src/com/intellij/javaee/InternalResourceProvider.java index 673540ef38e8..38777922ee35 100644 --- a/xml/xml-psi-impl/src/com/intellij/javaee/InternalResourceProvider.java +++ b/xml/xml-psi-impl/src/com/intellij/javaee/InternalResourceProvider.java @@ -63,5 +63,6 @@ public class InternalResourceProvider implements StandardResourceProvider{ // svg and mathML impl.addIgnoredResource(HtmlUtil.MATH_ML_NAMESPACE); impl.addIgnoredResource(HtmlUtil.SVG_NAMESPACE); + impl.addInternalResource("http://www.w3.org/1999/xlink", "xlink.dtd"); } } diff --git a/xml/xml-psi-impl/src/com/intellij/xml/HtmlXmlExtension.java b/xml/xml-psi-impl/src/com/intellij/xml/HtmlXmlExtension.java index 4ece939ffac0..e54a93394242 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/HtmlXmlExtension.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/HtmlXmlExtension.java @@ -3,6 +3,7 @@ package com.intellij.xml; import com.intellij.ide.highlighter.HtmlFileType; import com.intellij.psi.PsiFile; import com.intellij.psi.xml.XmlDocument; +import com.intellij.xml.util.HtmlUtil; import org.jetbrains.annotations.Nullable; /** @@ -19,6 +20,16 @@ public class HtmlXmlExtension extends DefaultXmlExtension { @Nullable @Override public String[][] getNamespacesFromDocument(XmlDocument parent, boolean declarationsExist) { - return super.getNamespacesFromDocument(parent, false); + String[][] namespaces = super.getNamespacesFromDocument(parent, false); + if (namespaces == null || !HtmlUtil.isHtml5Document(parent)) return namespaces; + + for (String[] namespace : namespaces) { + if ("xlink".equals(namespace[0])) return namespaces; + } + + String[][] newNamespaces = new String[namespaces.length + 1][2]; + System.arraycopy(namespaces, 0, newNamespaces, 0, namespaces.length); + newNamespaces[namespaces.length] = new String[] {"xlink", "http://www.w3.org/1999/xlink"}; + return newNamespaces; } }