diff --git a/community-resources/src/idea/IdeaApplicationInfo.xml b/community-resources/src/idea/IdeaApplicationInfo.xml index 29be79be394a..6c7b217eb54a 100644 --- a/community-resources/src/idea/IdeaApplicationInfo.xml +++ b/community-resources/src/idea/IdeaApplicationInfo.xml @@ -4,7 +4,7 @@ - + diff --git a/community-resources/src/idea_community_about.png b/community-resources/src/idea_community_about.png index 818498cc5e40..a80e0f0f31bd 100644 Binary files a/community-resources/src/idea_community_about.png and b/community-resources/src/idea_community_about.png differ diff --git a/community-resources/src/idea_community_about@2x.png b/community-resources/src/idea_community_about@2x.png index 81538802ccc1..5f5a262dbf8b 100644 Binary files a/community-resources/src/idea_community_about@2x.png and b/community-resources/src/idea_community_about@2x.png differ diff --git a/community-resources/src/idea_community_logo.png b/community-resources/src/idea_community_logo.png index 5c06cac1499d..7586d046cae8 100644 Binary files a/community-resources/src/idea_community_logo.png and b/community-resources/src/idea_community_logo.png differ diff --git a/community-resources/src/idea_community_logo@2x.png b/community-resources/src/idea_community_logo@2x.png index 0b801d0ea2bc..cf554799e5b1 100644 Binary files a/community-resources/src/idea_community_logo@2x.png and b/community-resources/src/idea_community_logo@2x.png differ 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 662ee4c5095e..47e41fd88cf1 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 @@ -299,6 +299,13 @@ public class InferenceSession { for (int i = 0; i < args.length; i++) { final PsiExpression arg = PsiUtil.skipParenthesizedExprDown(args[i]); if (arg != null) { + if (MethodCandidateInfo.isOverloadCheck() && arg instanceof PsiLambdaExpression) { + for (Object expr : MethodCandidateInfo.ourOverloadGuard.currentStack()) { + if (PsiTreeUtil.getParentOfType((PsiElement)expr, PsiLambdaExpression.class) == arg) { + return; + } + } + } final InferenceSession nestedCallSession = findNestedCallSession(arg); final PsiType parameterType = nestedCallSession.substituteWithInferenceVariables(getParameterType(parameters, i, siteSubstitutor, varargs)); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/expressions/NestedLambdaAdditionalConstraints.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/expressions/NestedLambdaAdditionalConstraints.java new file mode 100644 index 000000000000..8c3d94f99159 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/expressions/NestedLambdaAdditionalConstraints.java @@ -0,0 +1,13 @@ +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class MyTest { + void foo(Stream> listStream) { + listStream.map(lp -> lp.stream().map(p -> p.name).collect(Collectors.joining("/", "<", ">"))); + } + + public static class Person { + private String name = ""; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/resolve/LambdaChainConflictResolution.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/resolve/LambdaChainConflictResolution.java new file mode 100644 index 000000000000..3f94c927f603 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/resolve/LambdaChainConflictResolution.java @@ -0,0 +1,22 @@ +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.function.Function; + +class MyTest { + interface I { + List m(Set s); + } + + List foo(I i){return null;} + + List bar(Runnable l) {return null;} + List bar(Function s) {return null;} + + String baz(Set b, String x) {return null;} + List baz(Iterator s, Iterator i) {return null;} + + { + List l = foo(a -> bar(b -> baz(a, b))); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java index 644663c3e471..06872d91b9df 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Java8ExpressionsCheckTest.java @@ -31,6 +31,10 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase { doTestAllMethodCallExpressions(); } + public void testNestedLambdaAdditionalConstraints() throws Exception { + doTestAllMethodCallExpressions(); + } + private void doTestAllMethodCallExpressions() { configureByFile(BASE_PATH + "/" + getTestName(false) + ".java"); final Collection methodCallExpressions = PsiTreeUtil.findChildrenOfType(getFile(), PsiMethodCallExpression.class); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java index e14fcb25edc1..12734e50b936 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/TypeInference18Test.java @@ -43,6 +43,10 @@ public class TypeInference18Test extends ResolveTestCase { doTestMethodCall(); } + public void testLambdaChainConflictResolution() throws Exception { + doTestMethodCall(); + } + public void testCachedSubstitutionDuringOverloadResolution() throws Exception { PsiReference ref = configureByFile("/codeInsight/daemonCodeAnalyzer/lambda/resolve/" + getTestName(false) + ".java"); assertNotNull(ref); diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java index 048c186dc2b6..a4c58260d419 100644 --- a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java +++ b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java @@ -68,6 +68,7 @@ public class UISettings extends SimpleModificationTracker implements PersistentS public int RECENT_FILES_LIMIT = 50; public int CONSOLE_COMMAND_HISTORY_LIMIT = 300; public int EDITOR_TAB_LIMIT = 10; + public boolean REUSE_NOT_MODIFIED_TABS = false; public boolean ANIMATE_WINDOWS = true; @Deprecated //todo remove in IDEA 16 public int ANIMATION_SPEED = 4000; // Pixels per second diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java index 4045f08ecc79..fbead2687b6d 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontDescriptionPanel.java @@ -28,7 +28,9 @@ import com.intellij.ui.ColorPanel; import com.intellij.ui.HyperlinkAdapter; import com.intellij.ui.ListCellRendererWrapper; import com.intellij.ui.components.JBCheckBox; +import com.intellij.util.FontUtil; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -199,18 +201,19 @@ public class ColorAndFontDescriptionPanel extends JPanel { Pair baseDescriptor = description.getBaseAttributeDescriptor(); if (baseDescriptor != null && baseDescriptor.second.getDisplayName() != null) { String attrName = baseDescriptor.second.getDisplayName(); + String attrLabel = attrName.replaceAll(ColorOptionsTree.NAME_SEPARATOR, FontUtil.rightArrow(UIUtil.getLabelFont())); ColorSettingsPage settingsPage = baseDescriptor.first; String style = "
"; String tooltipText; String labelText; if (settingsPage != null) { String pageName = settingsPage.getDisplayName(); - tooltipText = "'" + attrName + "' from
'" + pageName + "' section"; - labelText = style + "'" + attrName + "'
of " + pageName; + tooltipText = "'" + attrLabel + "' from
'" + pageName + "' section"; + labelText = style + "'" + attrLabel + "'
of
" + pageName; } else { - tooltipText = attrName; - labelText = style + attrName + "
 "; + tooltipText = attrLabel; + labelText = style + attrLabel + "
 "; } myInheritanceLabel.setText(labelText); diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorOptionsTree.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorOptionsTree.java new file mode 100644 index 000000000000..abdce373e5ba --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorOptionsTree.java @@ -0,0 +1,201 @@ +/* + * Copyright 2000-2015 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.application.options.colors; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.TreeSpeedSearch; +import com.intellij.ui.treeStructure.Tree; +import com.intellij.util.containers.ContainerUtil; +import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.tree.*; +import java.util.*; + +/** + * @author Rustam Vishnyakov + */ +public class ColorOptionsTree extends Tree { + private final String myCategoryName; + private final DefaultTreeModel myTreeModel; + + public final static String NAME_SEPARATOR = "//"; + + private static final Comparator ATTR_COMPARATOR = new Comparator() { + @Override + public int compare(EditorSchemeAttributeDescriptor o1, EditorSchemeAttributeDescriptor o2) { + return StringUtil.naturalCompare(o1.toString(), o2.toString()); + } + }; + + public ColorOptionsTree(@NotNull String categoryName) { + super(createTreeModel()); + myTreeModel = (DefaultTreeModel)getModel(); + setRootVisible(false); + getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + myCategoryName = categoryName; + new TreeSpeedSearch(this, TreeSpeedSearch.NODE_DESCRIPTOR_TOSTRING, true); + } + + public void fillOptions(@NotNull ColorAndFontOptions options) { + DefaultMutableTreeNode root = new DefaultMutableTreeNode(); + for (EditorSchemeAttributeDescriptor description : getOrderedDescriptors(options)) { + if (!description.getGroup().equals(myCategoryName)) continue; + List path = extractPath(description); + if (path != null && path.size() > 1) { + MyTreeNode groupNode = ensureGroup(root, path, 0); + groupNode.add(new MyTreeNode(description, path.get(path.size() - 1))); + } + else { + root.add(new MyTreeNode(description)); + } + } + myTreeModel.setRoot(root); + } + + private static TreeModel createTreeModel() { + return new DefaultTreeModel(new DefaultMutableTreeTableNode()); + } + + private Collection getOrderedDescriptors(@NotNull ColorAndFontOptions options) { + ArrayList list = ContainerUtil.newArrayList(); + for (EditorSchemeAttributeDescriptor description : options.getCurrentDescriptions()) { + if (!description.getGroup().equals(myCategoryName)) continue; + list.add(description); + } + Collections.sort(list, ATTR_COMPARATOR); + return list; + } + + @Nullable + public ColorAndFontDescription getSelectedDescriptor() { + Object selectedNode = getLastSelectedPathComponent(); + if (selectedNode instanceof DefaultMutableTreeNode) { + Object selectedValue = ((DefaultMutableTreeNode)selectedNode).getUserObject(); + if (selectedValue instanceof ColorAndFontDescription) { + return (ColorAndFontDescription)selectedValue; + } + } + return null; + } + + public void selectOptionByType(@NotNull final String attributeType) { + selectPath(findOption(myTreeModel.getRoot(), new DescriptorMatcher() { + @Override + public boolean matches(@NotNull Object data) { + if (data instanceof EditorSchemeAttributeDescriptor) { + return attributeType.equals(((EditorSchemeAttributeDescriptor)data).getType()); + } + return false; + } + })); + } + + public void selectOptionByName(@NotNull final String optionName) { + selectPath(findOption(myTreeModel.getRoot(), new DescriptorMatcher() { + @Override + public boolean matches(@NotNull Object data) { + return StringUtil.containsIgnoreCase(data.toString(), optionName); + } + })); + } + + @Nullable + private TreePath findOption(@NotNull Object nodeObject, @NotNull DescriptorMatcher matcher) { + for (int i = 0; i < myTreeModel.getChildCount(nodeObject); i ++) { + Object childObject = myTreeModel.getChild(nodeObject, i); + if (childObject instanceof MyTreeNode) { + Object data = ((MyTreeNode)childObject).getUserObject(); + if (matcher.matches(data)) { + return new TreePath(myTreeModel.getPathToRoot((MyTreeNode)childObject)); + } + } + TreePath pathInChild = findOption(childObject, matcher); + if (pathInChild != null) return pathInChild; + } + return null; + } + + private void selectPath(@Nullable TreePath path) { + if (path != null) { + setSelectionPath(path); + scrollPathToVisible(path); + } + } + + @Nullable + private static List extractPath(@NotNull EditorSchemeAttributeDescriptor descriptor) { + if (descriptor instanceof ColorAndFontDescription) { + String name = descriptor.toString(); + List path = new ArrayList(); + int separatorStart = name.indexOf(NAME_SEPARATOR); + int nextChunkStart = 0; + while(separatorStart > 0) { + path.add(name.substring(nextChunkStart, separatorStart)); + nextChunkStart = separatorStart + NAME_SEPARATOR.length(); + separatorStart = name.indexOf(NAME_SEPARATOR, nextChunkStart); + } + if (nextChunkStart < name.length()) { + path.add(name.substring(nextChunkStart)); + } + return path; + } + return null; + } + + private static class MyTreeNode extends DefaultMutableTreeNode { + private final String myName; + + public MyTreeNode(@NotNull EditorSchemeAttributeDescriptor descriptor, @NotNull String name) { + super(descriptor); + myName = name; + } + + public MyTreeNode(@NotNull EditorSchemeAttributeDescriptor descriptor) { + super(descriptor); + myName = descriptor.toString(); + } + + public MyTreeNode(@NotNull String groupName) { + super(groupName); + myName = groupName; + } + + @Override + public String toString() { + return myName; + } + + } + + private interface DescriptorMatcher { + boolean matches(@NotNull Object data); + } + + private static MyTreeNode ensureGroup(@NotNull DefaultMutableTreeNode root, @NotNull List path, int index) { + String groupName = path.get(index ++); + for (int i = 0; i < root.getChildCount(); i ++) { + TreeNode child = root.getChildAt(i); + if (child instanceof MyTreeNode && groupName.equals(child.toString())) { + return index < path.size() - 1 ? ensureGroup((MyTreeNode)child, path, index) : (MyTreeNode)child; + } + } + MyTreeNode groupNode = new MyTreeNode(groupName); + root.add(groupNode); + return index < path.size() - 1 ? ensureGroup(groupNode, path, index) : groupNode; + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorSettingsUtil.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorSettingsUtil.java index 28123007bd2f..a25a6a3c2815 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorSettingsUtil.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorSettingsUtil.java @@ -96,6 +96,9 @@ public class ColorSettingsUtil { @NotNull private static String toDisplayName(@NotNull TextAttributesKey attributesKey) { - return StringUtil.capitalize(attributesKey.getExternalName().toLowerCase().replaceAll("_", " ")); + //noinspection StringToUpperCaseOrToLowerCaseWithoutLocale + return OptionsBundle.message( + "options.java.attribute.descriptor.errors.group", + StringUtil.capitalize(attributesKey.getExternalName().toLowerCase().replaceAll("_", " "))); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/OptionsPanelImpl.java b/platform/lang-impl/src/com/intellij/application/options/colors/OptionsPanelImpl.java index 510669bd5434..3d78329c00fa 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/OptionsPanelImpl.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/OptionsPanelImpl.java @@ -20,35 +20,24 @@ import com.intellij.ide.DataManager; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.options.ex.Settings; import com.intellij.openapi.util.ActionCallback; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.CollectionListModel; -import com.intellij.ui.ListScrollingUtil; -import com.intellij.ui.ListSpeedSearch; import com.intellij.ui.ScrollPaneFactory; -import com.intellij.ui.components.JBList; import com.intellij.util.EventDispatcher; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBUI; import javax.swing.*; import javax.swing.event.HyperlinkEvent; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; import javax.swing.text.BadLocationException; import javax.swing.text.Element; import java.awt.*; import java.awt.event.ActionEvent; -import java.util.*; +import java.util.HashSet; +import java.util.Set; public class OptionsPanelImpl extends JPanel implements OptionsPanel { - private static final Comparator ATTR_COMPARATOR = new Comparator() { - @Override - public int compare(EditorSchemeAttributeDescriptor o1, EditorSchemeAttributeDescriptor o2) { - return StringUtil.naturalCompare(o1.toString(), o2.toString()); - } - }; - private final JBList myOptionsList; + + private final ColorOptionsTree myOptionsTree; private final ColorAndFontDescriptionPanel myOptionsPanel; private final ColorAndFontOptions myOptions; @@ -56,7 +45,6 @@ public class OptionsPanelImpl extends JPanel implements OptionsPanel { private final String myCategoryName; private final EventDispatcher myDispatcher = EventDispatcher.create(ColorAndFontSettingsListener.class); - private final CollectionListModel myListModel; public OptionsPanelImpl(ColorAndFontOptions options, SchemesPanel schemesProvider, @@ -96,32 +84,17 @@ public class OptionsPanelImpl extends JPanel implements OptionsPanel { } }; - myListModel = new CollectionListModel(); - myOptionsList = new JBList(myListModel); - new ListSpeedSearch(myOptionsList); + myOptionsTree = new ColorOptionsTree(myCategoryName); - myOptionsList.addListSelectionListener(new ListSelectionListener() { + myOptionsTree.addTreeSelectionListener(new TreeSelectionListener() { @Override - public void valueChanged(ListSelectionEvent e) { + public void valueChanged(TreeSelectionEvent e) { if (!mySchemesProvider.areSchemesLoaded()) return; processListValueChanged(); } }); - myOptionsList.setCellRenderer(new DefaultListCellRenderer(){ - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - if (value instanceof ColorAndFontDescription) { - setIcon(((ColorAndFontDescription)value).getIcon()); - setToolTipText(((ColorAndFontDescription)value).getToolTip()); - } - return component; - } - }); - myOptionsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myOptionsList); + JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myOptionsTree); scrollPane.setPreferredSize(JBUI.size(230, 60)); JPanel north = new JPanel(new BorderLayout()); north.add(scrollPane, BorderLayout.CENTER); @@ -136,40 +109,18 @@ public class OptionsPanelImpl extends JPanel implements OptionsPanel { } private void processListValueChanged() { - Object selectedValue = myOptionsList.getSelectedValue(); - ColorAndFontDescription description = (ColorAndFontDescription)selectedValue; - ColorAndFontDescriptionPanel optionsPanel = myOptionsPanel; - if (description == null) { - optionsPanel.resetDefault(); - return; + ColorAndFontDescription description = myOptionsTree.getSelectedDescriptor(); + if (description != null) { + myOptionsPanel.reset(description); + myDispatcher.getMulticaster().selectedOptionChanged(description); + } + else { + myOptionsPanel.resetDefault(); } - optionsPanel.reset(description); - - myDispatcher.getMulticaster().selectedOptionChanged(description); - } private void fillOptionsList() { - int selIndex = myOptionsList.getSelectedIndex(); - - myListModel.removeAll(); - - ArrayList list = ContainerUtil.newArrayList(); - for (EditorSchemeAttributeDescriptor description : myOptions.getCurrentDescriptions()) { - if (!description.getGroup().equals(myCategoryName)) continue; - list.add(description); - } - Collections.sort(list, ATTR_COMPARATOR); - myListModel.add(list); - if (selIndex >= 0) { - myOptionsList.setSelectedIndex(selIndex); - } - ListScrollingUtil.ensureSelectionExists(myOptionsList); - - Object selected = myOptionsList.getSelectedValue(); - if (selected instanceof EditorSchemeAttributeDescriptor) { - myDispatcher.getMulticaster().selectedOptionChanged(selected); - } + myOptionsTree.fillOptions(myOptions); } @Override @@ -184,53 +135,37 @@ public class OptionsPanelImpl extends JPanel implements OptionsPanel { } @Override - public Runnable showOption(String attributeDisplayName) { - final int index = getAttributeIndex(attributeDisplayName, true); - return index < 0 ? null : new Runnable() { + public Runnable showOption(final String attributeDisplayName) { + return new Runnable() { @Override public void run() { - ListScrollingUtil.selectItem(myOptionsList, index); - myOptionsList.requestFocus(); + myOptionsTree.selectOptionByName(attributeDisplayName); } }; } - private int getAttributeIndex(final String option, final boolean byDisplayNamePlease) { - return ContainerUtil.indexOf(myListModel.getItems(), new Condition() { - @Override - public boolean value(EditorSchemeAttributeDescriptor o) { - return StringUtil.naturalCompare(byDisplayNamePlease ? o.toString() : o.getType(), option) == 0; - } - }); - } - @Override public void applyChangesToScheme() { - Object selectedValue = myOptionsList.getSelectedValue(); - if (selectedValue instanceof ColorAndFontDescription) { - myOptionsPanel.apply((ColorAndFontDescription)selectedValue, myOptions.getSelectedScheme()); + ColorAndFontDescription descriptor = myOptionsTree.getSelectedDescriptor(); + if (descriptor != null) { + myOptionsPanel.apply(descriptor, myOptions.getSelectedScheme()); } } @Override public void selectOption(String attributeType) { - int index = getAttributeIndex(attributeType, false); - if (index < 0) return; - ListScrollingUtil.selectItem(myOptionsList, index); + myOptionsTree.selectOptionByType(attributeType); } @Override public Set processListOptions() { HashSet result = new HashSet(); EditorSchemeAttributeDescriptor[] descriptions = myOptions.getCurrentDescriptions(); - for (EditorSchemeAttributeDescriptor description : descriptions) { if (description.getGroup().equals(myCategoryName)) { result.add(description.toString()); } } - - return result; } } diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form index e3992ac1a937..e36d07265634 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form @@ -127,7 +127,7 @@ - + @@ -154,6 +154,14 @@ + + + + + + + + diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java index edcb1e05d1f7..6bd9b98ad296 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java @@ -48,6 +48,7 @@ public class EditorTabsConfigurable implements EditorOptionsProvider { private JCheckBox myShowDirectoryInTabCheckBox; private JRadioButton myActivateRightNeighbouringTabRadioButton; private JCheckBox myHideTabsCheckbox; + private JCheckBox myReuseNotModifiedTabsCheckBox; public EditorTabsConfigurable() { myEditorTabPlacement.setModel(new DefaultComboBoxModel(new Object[]{ @@ -121,6 +122,7 @@ public class EditorTabsConfigurable implements EditorOptionsProvider { myHideKnownExtensions.setSelected(uiSettings.HIDE_KNOWN_EXTENSION_IN_TABS); myShowDirectoryInTabCheckBox.setSelected(uiSettings.SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES); myEditorTabLimitField.setText(Integer.toString(uiSettings.EDITOR_TAB_LIMIT)); + myReuseNotModifiedTabsCheckBox.setSelected(uiSettings.REUSE_NOT_MODIFIED_TABS); myShowCloseButtonOnCheckBox.setSelected(uiSettings.SHOW_CLOSE_BUTTON); if (uiSettings.CLOSE_NON_MODIFIED_FILES_FIRST) { @@ -168,13 +170,16 @@ public class EditorTabsConfigurable implements EditorOptionsProvider { uiSettings.HIDE_KNOWN_EXTENSION_IN_TABS = hide; boolean dir = myShowDirectoryInTabCheckBox.isSelected(); - if (uiSettings.SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES != hide) uiSettingsChanged = true; - uiSettings.SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES = myShowDirectoryInTabCheckBox.isSelected(); + if (uiSettings.SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES != dir) uiSettingsChanged = true; + uiSettings.SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES = dir; uiSettings.CLOSE_NON_MODIFIED_FILES_FIRST = myCloseNonModifiedFilesFirstRadio.isSelected(); uiSettings.ACTIVATE_MRU_EDITOR_ON_CLOSE = myActivateMRUEditorOnCloseRadio.isSelected(); uiSettings.ACTIVATE_RIGHT_EDITOR_ON_CLOSE = myActivateRightNeighbouringTabRadioButton.isSelected(); + if (isModified(myReuseNotModifiedTabsCheckBox, uiSettings.REUSE_NOT_MODIFIED_TABS)) uiSettingsChanged = true; + uiSettings.REUSE_NOT_MODIFIED_TABS = myReuseNotModifiedTabsCheckBox.isSelected(); + String temp = myEditorTabLimitField.getText(); if (temp.trim().length() > 0) { try { @@ -198,6 +203,7 @@ public class EditorTabsConfigurable implements EditorOptionsProvider { boolean isModified = isModified(myCbModifiedTabsMarkedWithAsterisk, uiSettings.MARK_MODIFIED_TABS_WITH_ASTERISK); isModified |= isModified(myShowTabsTooltipsCheckBox, uiSettings.SHOW_TABS_TOOLTIPS); isModified |= isModified(myEditorTabLimitField, uiSettings.EDITOR_TAB_LIMIT); + isModified |= isModified(myReuseNotModifiedTabsCheckBox, uiSettings.REUSE_NOT_MODIFIED_TABS); int tabPlacement = ((Integer)myEditorTabPlacement.getSelectedItem()).intValue(); isModified |= tabPlacement != uiSettings.EDITOR_TAB_PLACEMENT; isModified |= myHideKnownExtensions.isSelected() != uiSettings.HIDE_KNOWN_EXTENSION_IN_TABS; 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 5b0beefd98d5..818b81fbef94 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 @@ -1061,6 +1061,11 @@ public class EditorWindow { private void doTrimSize(int limit, @Nullable VirtualFile fileToIgnore, boolean closeNonModifiedFilesFirst, boolean transferFocus) { LinkedHashSet closingOrder = getTabClosingOrder(closeNonModifiedFilesFirst); + VirtualFile selectedFile = getSelectedFile(); + if (shouldCloseSelected()) { + defaultCloseFile(selectedFile, transferFocus); + closingOrder.remove(selectedFile); + } for (VirtualFile file : closingOrder) { if (myTabbedPane.getTabCount() <= limit || myTabbedPane.getTabCount() == 0 || areAllTabsPinned(fileToIgnore)) { @@ -1120,6 +1125,20 @@ public class EditorWindow { return closingOrder; } + private boolean shouldCloseSelected() { + if (!UISettings.getInstance().REUSE_NOT_MODIFIED_TABS) return false; + if (!myOwner.getManager().getProject().isInitialized()) return false; + VirtualFile file = getSelectedFile(); + if (file == null) return false; + if (!isFileOpen(file)) return false; + if (isFilePinned(file)) return false; + EditorWithProviderComposite composite = findFileComposite(file); + if (composite == null) return false; + Component owner = IdeFocusManager.getInstance(myOwner.getManager().getProject()).getFocusOwner(); + if (owner == null || !SwingUtilities.isDescendingFrom(owner, composite.getSelectedEditor().getComponent())) return false; + return !myOwner.getManager().isChanged(composite); + } + private static boolean isFileModified(EditorComposite composite, VirtualFile file) { return composite != null && (composite.getInitialFileTimeStamp() == file.getTimeStamp() || composite.isModified()); } diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index ef7f89109628..37550debb168 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -377,6 +377,7 @@ label.collapse.by.default=Collapse by default: checkbox.show.code.folding.outline=Show code folding outline group.tab.appearance=Tab Appearance editbox.tab.limit=Tab limit: +checkbox.smart.tab.reuse=Navigation from not-modified tab will reuse it combobox.editor.tab.placement=Placement: checkbox.editor.tabs.in.single.row=Show tabs in single row checkbox.editor.tabs.show.close.button=Show "close" button on editor tabs diff --git a/platform/platform-resources-en/src/messages/OptionsBundle.properties b/platform/platform-resources-en/src/messages/OptionsBundle.properties index 749b27761dbf..a08997ceafa2 100644 --- a/platform/platform-resources-en/src/messages/OptionsBundle.properties +++ b/platform/platform-resources-en/src/messages/OptionsBundle.properties @@ -12,13 +12,13 @@ options.custom.attribute.descriptor.block.comment=Block comment options.custom.attribute.descriptor.valid.string.escape=Valid string escape options.custom.attribute.descriptor.invalid.string.escape=Invalid string escape -options.general.attribute.descriptor.default.text=Default text -options.general.attribute.descriptor.folded.text=Folded text -options.general.attribute.descriptor.deleted.text=Deleted text -options.general.attribute.descriptor.search.result=Search result -options.general.attribute.descriptor.search.result.write.access=Search result (write access) -options.general.attribute.descriptor.text.search.result=Text search result -options.general.attribute.descriptor.template.variable=Template variable +options.general.attribute.descriptor.default.text=Text//Default text +options.general.attribute.descriptor.folded.text=Text//Folded text +options.general.attribute.descriptor.deleted.text=Text//Deleted text +options.general.attribute.descriptor.search.result=Search Results//Search result +options.general.attribute.descriptor.search.result.write.access=Search Results//Search result (write access) +options.general.attribute.descriptor.text.search.result=Search Results//Text search result +options.general.attribute.descriptor.template.variable=Templates//Template variable options.html.attribute.descriptor.comment=Comment options.html.attribute.descriptor.code=HTML code @@ -63,11 +63,12 @@ options.java.attribute.descriptor.javadoc.comment=JavaDoc comment options.java.attribute.descriptor.javadoc.tag=JavaDoc tag options.java.attribute.descriptor.javadoc.tag.value=JavaDoc tag value options.java.attribute.descriptor.javadoc.markup=JavaDoc markup -options.java.attribute.descriptor.unknown.symbol=Unknown symbol -options.java.attribute.descriptor.error=Error -options.java.attribute.descriptor.warning=Warning -options.java.attribute.descriptor.deprecated.symbol=Deprecated symbol -options.java.attribute.descriptor.unused.symbol=Unused symbol +options.java.attribute.descriptor.errors.group=Errors and Warnings//{0} +options.java.attribute.descriptor.unknown.symbol=Errors and Warnings//Unknown symbol +options.java.attribute.descriptor.error=Errors and Warnings//Error +options.java.attribute.descriptor.warning=Errors and Warnings//Warning +options.java.attribute.descriptor.deprecated.symbol=Errors and Warnings//Deprecated symbol +options.java.attribute.descriptor.unused.symbol=Errors and Warnings//Unused symbol options.java.attribute.descriptor.class=Class options.java.attribute.descriptor.anonymous.class=Anonymous class options.java.attribute.descriptor.type.parameter=Type parameter @@ -89,8 +90,8 @@ options.java.attribute.descriptor.constructor.declaration=Constructor declaratio options.java.attribute.descriptor.static.method=Static method options.java.attribute.descriptor.abstract.method=Abstract method options.java.attribute.descriptor.inherited.method=Inherited method -options.java.attribute.descriptor.matched.brace=Matched brace -options.java.attribute.descriptor.unmatched.brace=Unmatched brace +options.java.attribute.descriptor.matched.brace=Code//Matched brace +options.java.attribute.descriptor.unmatched.brace=Code//Unmatched brace options.java.attribute.descriptor.bad.character=Bad character options.java.attribute.descriptor.breakpoint.line=Breakpoint line options.java.attribute.descriptor.execution.point=Execution point @@ -113,89 +114,89 @@ options.xml.attribute.descriptor.tag.data=Tag data options.xml.attribute.descriptor.descriptor.entity,reference=Entity reference #Color descriptors -options.general.color.descriptor.background.in.readonly.files=Background in readonly files -options.deneral.color.descriptor.readonly.fragment.background=Readonly fragment background -options.general.color.descriptor.gutter.background=Gutter background -options.general.color.descriptor.notification.background=Notification background -options.general.color.descriptor.selection.background=Selection background -options.general.color.descriptor.selection.foreground=Selection foreground -options.general.color.descriptor.caret=Caret -options.general.color.descriptor.caret.row=Caret row -options.general.color.descriptor.right.margin=Right margin -options.general.color.descriptor.whitespaces=Whitespaces -options.general.color.descriptor.indent.guide=Vertical indent guide -options.general.color.descriptor.indent.guide.selected=Selected vertical indent guide -options.general.color.descriptor.line.number=Line number -options.general.color.descriptor.vcs.annotations=VCS annotations -options.general.color.descriptor.vcs.annotations.merged=VCS annotations (merged from) -options.general.color.descriptor.tearline=Tear line -options.general.color.descriptor.tearline.selected=Selected tear line -options.general.color.descriptor.added.lines=Gutter - Added lines -options.general.color.descriptor.modified.lines=Gutter - Modified lines -options.general.color.descriptor.deleted.lines=Gutter - Deleted lines -options.general.color.descriptor.whitespaces.modified.lines=Gutter - Lines with whitespace-only modifications -options.general.color.descriptor.border.lines=Gutter - Border for changed lines -options.general.color.descriptor.console.background=Console background -options.general.color.descriptor.console.stdout=Console standard output -options.general.color.descriptor.console.stderr=Console error output -options.general.color.descriptor.console.expired=Log console expired entry -options.general.color.descriptor.console.warning=Log console warning -options.general.color.descriptor.console.logError=Log console error -options.general.color.descriptor.console.stdin=Console user input -options.general.color.descriptor.console.system.output=Console system output -options.general.color.descriptor.hyperlink.new=Hyperlink -options.general.color.descriptor.hyperlink.followed=Followed hyperlink -options.general.color.descriptor.reference.hyperlink=Reference hyperlink -options.general.color.descriptor.todo.defaults=TODO defaults -options.general.color.descriptor.bookmarks=Bookmarks -options.general.color.soft.wrap.sign=Soft wrap sign +options.general.color.descriptor.background.in.readonly.files=Text//Background in readonly files +options.deneral.color.descriptor.readonly.fragment.background=Text//Readonly fragment background +options.general.color.descriptor.gutter.background=Gutter//Background +options.general.color.descriptor.notification.background=Editor//Notification background +options.general.color.descriptor.selection.background=Editor//Selection background +options.general.color.descriptor.selection.foreground=Editor//Selection foreground +options.general.color.descriptor.caret=Editor//Caret +options.general.color.descriptor.caret.row=Editor//Caret row +options.general.color.descriptor.right.margin=Editor//Right margin +options.general.color.descriptor.whitespaces=Text//Whitespaces +options.general.color.descriptor.indent.guide=Code//Vertical indent guide +options.general.color.descriptor.indent.guide.selected=Code//Selected vertical indent guide +options.general.color.descriptor.line.number=Code//Line number +options.general.color.descriptor.vcs.annotations=VCS Annotations//Regular +options.general.color.descriptor.vcs.annotations.merged=VCS Annotations//Merged from +options.general.color.descriptor.tearline=Editor//Tear line +options.general.color.descriptor.tearline.selected=Editor//Tear line selection +options.general.color.descriptor.added.lines=Gutter//Added lines +options.general.color.descriptor.modified.lines=Gutter//Modified lines +options.general.color.descriptor.deleted.lines=Gutter//Deleted lines +options.general.color.descriptor.whitespaces.modified.lines=Gutter//Lines with whitespace-only modifications +options.general.color.descriptor.border.lines=Gutter//Border for changed lines +options.general.color.descriptor.console.background=Console//Background +options.general.color.descriptor.console.stdout=Console//Standard output +options.general.color.descriptor.console.stderr=Console//Error output +options.general.color.descriptor.console.expired=Log Console//Expired entry +options.general.color.descriptor.console.warning=Log Console//Warning +options.general.color.descriptor.console.logError=Log Console//Error +options.general.color.descriptor.console.stdin=Console//User input +options.general.color.descriptor.console.system.output=Console//System output +options.general.color.descriptor.hyperlink.new=Hyperlinks//Unfollowed +options.general.color.descriptor.hyperlink.followed=Hyperlinks//Followed +options.general.color.descriptor.reference.hyperlink=Hyperlinks//Reference +options.general.color.descriptor.todo.defaults=Code//TODO defaults +options.general.color.descriptor.bookmarks=Editor//Bookmarks +options.general.color.soft.wrap.sign=Text//Soft wrap sign options.language.defaults.display.name=Language Defaults options.language.defaults.keyword=Keyword -options.language.defaults.identifier=Identifier -options.language.defaults.string=String -options.language.defaults.valid.esc.seq=Valid escape sequence -options.language.defaults.invalid.esc.seq=Invalid escape sequence +options.language.defaults.identifier=Identifiers//Default +options.language.defaults.string=String//String text +options.language.defaults.valid.esc.seq=String//Escape Sequence//Valid +options.language.defaults.invalid.esc.seq=String//Escape Sequence//Invalid options.language.defaults.number=Number -options.language.defaults.operation=Operation sign -options.language.defaults.braces=Braces -options.language.defaults.parentheses=Parentheses -options.language.defaults.brackets=Brackets -options.language.defaults.dot=Dot -options.language.defaults.comma=Comma -options.language.defaults.semicolon=Semicolon -options.language.defaults.line.comment=Line comment -options.language.defaults.block.comment=Block comment -options.language.defaults.doc.comment=Doc comment -options.language.defaults.doc.markup=Doc comment markup -options.language.defaults.doc.tag=Doc comment tag -options.language.defaults.doc.tag.value=Doc comment tag value -options.language.defaults.label=Label -options.language.defaults.constant=Constant -options.language.defaults.local.variable=Local variable -options.language.defaults.global.variable=Global variable -options.language.defaults.function.declaration=Function declaration -options.language.defaults.function.call=Function call -options.language.defaults.parameter=Parameter -options.language.defaults.interface.name=Interface name -options.language.defaults.class.name=Class name -options.language.defaults.class.reference=Class reference -options.language.defaults.instance.method=Instance method -options.language.defaults.instance.field=Instance field -options.language.defaults.static.method=Static method -options.language.defaults.static.field=Static field +options.language.defaults.operation=Braces and Operators//Operation sign +options.language.defaults.braces=Braces and Operators//Braces +options.language.defaults.parentheses=Braces and Operators//Parentheses +options.language.defaults.brackets=Braces and Operators//Brackets +options.language.defaults.dot=Braces and Operators//Dot +options.language.defaults.comma=Braces and Operators//Comma +options.language.defaults.semicolon=Braces and Operators//Semicolon +options.language.defaults.line.comment=Comments//Line comment +options.language.defaults.block.comment=Comments//Block comment +options.language.defaults.doc.comment=Comments//Doc Comment//Text +options.language.defaults.doc.markup=Comments//Doc Comment//Markup +options.language.defaults.doc.tag=Comments//Doc Comment//Tag +options.language.defaults.doc.tag.value=Comments//Doc Comment//Tag value +options.language.defaults.label=Identifiers//Label +options.language.defaults.constant=Identifiers//Constant +options.language.defaults.local.variable=Identifiers//Local variable +options.language.defaults.global.variable=Identifiers//Global variable +options.language.defaults.function.declaration=Identifiers//Function declaration +options.language.defaults.function.call=Identifiers//Function call +options.language.defaults.parameter=Identifiers//Parameter +options.language.defaults.interface.name=Classes//Interface name +options.language.defaults.class.name=Classes//Class name +options.language.defaults.class.reference=Classes//Class reference +options.language.defaults.instance.method=Classes//Instance method +options.language.defaults.instance.field=Classes//Instance field +options.language.defaults.static.method=Classes//Static method +options.language.defaults.static.field=Classes//Static field options.language.defaults.template.language=Template language -options.language.defaults.markup.tag=Markup Tag -options.language.defaults.markup.attribute=Markup Attribute -options.language.defaults.markup.entity=Markup Entity -options.language.defaults.predefined=Predefined symbol +options.language.defaults.markup.tag=Markup//Tag +options.language.defaults.markup.attribute=Markup//Attribute +options.language.defaults.markup.entity=Markup//Entity +options.language.defaults.predefined=Identifiers//Predefined symbol options.language.defaults.metadata=Metadata -options.java.color.descriptor.full.coverage=Full line coverage -options.java.color.descriptor.partial.coverage=Partial line coverage -options.java.color.descriptor.none.coverage=Uncovered line -options.java.color.descriptor.method.separator.color=Method separator color +options.java.color.descriptor.full.coverage=Line coverage//Full +options.java.color.descriptor.partial.coverage=Line coverage//Partial +options.java.color.descriptor.none.coverage=Line coverage//Uncovered +options.java.color.descriptor.method.separator.color=Code//Method separator color options.custom.display.name=Custom options.general.display.name=General options.html.display.name=HTML @@ -260,36 +261,36 @@ project.file.read.only.error.message=The project file is read-only.\nThe setting template.project.settings.display.name=Template Project Settings #0 - project name project.settings.display.name=Project Settings [{0}] -options.java.attribute.descriptor.weak.warning=Weak Warning -options.java.attribute.descriptor.server.problems=Problem from server -options.java.attribute.descriptor.server.duplicate=Duplicate from server -options.general.color.descriptor.injected.language.fragment=Injected language fragment -options.general.attribute.descriptior.identifier.under.caret=Identifier under caret -options.general.attribute.descriptior.identifier.under.caret.write=Identifier under caret (write) +options.java.attribute.descriptor.weak.warning=Errors and Warnings//Weak Warning +options.java.attribute.descriptor.server.problems=Errors and Warnings//Problem from server +options.java.attribute.descriptor.server.duplicate=Errors and Warnings//Duplicate from server +options.general.color.descriptor.injected.language.fragment=Code//Injected language fragment +options.general.attribute.descriptior.identifier.under.caret=Code//Identifier under caret +options.general.attribute.descriptior.identifier.under.caret.write=Code//Identifier under caret (write) # Console settings color.settings.console.name=Console Colors color.settings.console.output=IRB Output -color.settings.console.black=ANSI Black -color.settings.console.red=ANSI Red -color.settings.console.green=ANSI Green -color.settings.console.yellow=ANSI Yellow -color.settings.console.blue=ANSI Blue -color.settings.console.magenta=ANSI Magenta -color.settings.console.cyan=ANSI Cyan -color.settings.console.gray=ANSI Gray +color.settings.console.black=ANSI Colors//Black +color.settings.console.red=ANSI Colors//Red +color.settings.console.green=ANSI Colors//Green +color.settings.console.yellow=ANSI Colors//Yellow +color.settings.console.blue=ANSI Colors//Blue +color.settings.console.magenta=ANSI Colors//Magenta +color.settings.console.cyan=ANSI Colors//Cyan +color.settings.console.gray=ANSI Colors//Gray -color.settings.console.darkGray=ANSI Dark Gray -color.settings.console.redBright=ANSI Bright Red -color.settings.console.greenBright=ANSI Bright Green -color.settings.console.yellowBright=ANSI Bright Yellow -color.settings.console.blueBright=ANSI Bright Blue -color.settings.console.magentaBright=ANSI Bright Magenta -color.settings.console.cyanBright=ANSI Bright Cyan -color.settings.console.white=ANSI White +color.settings.console.darkGray=ANSI Colors//Dark Gray +color.settings.console.redBright=ANSI Colors//Bright Red +color.settings.console.greenBright=ANSI Colors//Bright Green +color.settings.console.yellowBright=ANSI Colors//Bright Yellow +color.settings.console.blueBright=ANSI Colors//Bright Blue +color.settings.console.magentaBright=ANSI Colors//Bright Magenta +color.settings.console.cyanBright=ANSI Colors//Bright Cyan +color.settings.console.white=ANSI Colors//White -options.general.attribute.descriptor.live.template=Live Template +options.general.attribute.descriptor.live.template=Templates//Live Template exportable.EditorSettings.presentable.name=Editor exportable.AbbreviationManager.presentable.name=Actions diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index f48ed7465161..ce9d977b2907 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1634,22 +1634,28 @@ public class UIUtil { boolean toolWindow, boolean drawTopLine, boolean drawBottomLine) { - g.setColor(getPanelBackground()); - g.fillRect(x, 0, width, height); - - ((Graphics2D)g).setPaint(getGradientPaint(0, 0, new Color(0, 0, 0, 5), 0, height, new Color(0, 0, 0, 20))); - g.fillRect(x, 0, width, height); - - g.setColor(new Color(0, 0, 0, toolWindow ? 90 : 50)); - if (drawTopLine) g.drawLine(x, 0, width, 0); - if (drawBottomLine) g.drawLine(x, height - 1, width, height - 1); - - g.setColor(isUnderDarcula() ? Gray._255.withAlpha(30) : new Color(255, 255, 255, 100)); - g.drawLine(x, drawTopLine ? 1 : 0, width, drawTopLine ? 1 : 0); - - if (active) { - g.setColor(new Color(100, 150, 230, toolWindow ? 50 : 30)); + height++; + GraphicsConfig config = GraphicsUtil.disableAAPainting(g); + try { + g.setColor(getPanelBackground()); g.fillRect(x, 0, width, height); + + ((Graphics2D)g).setPaint(getGradientPaint(0, 0, new Color(0, 0, 0, 5), 0, height, new Color(0, 0, 0, 20))); + g.fillRect(x, 0, width, height); + + g.setColor(new Color(0, 0, 0, toolWindow ? 90 : 50)); + if (drawTopLine) g.drawLine(x, 0, width, 0); + if (drawBottomLine) g.drawLine(x, height - 1, width, height - 1); + + g.setColor(isUnderDarcula() ? Gray._255.withAlpha(30) : new Color(255, 255, 255, 100)); + g.drawLine(x, drawTopLine ? 1 : 0, width, drawTopLine ? 1 : 0); + + if (active) { + g.setColor(new Color(100, 150, 230, toolWindow ? 50 : 30)); + g.fillRect(x, 0, width, height); + } + } finally { + config.restore(); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java index 33581305e6ee..528d49d7dc53 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java @@ -103,6 +103,7 @@ public class XDebuggerExpressionComboBox extends XDebuggerEditorBase { @Override protected void onEditorCreate(EditorEx editor) { editor.putUserData(DebuggerCopyPastePreprocessor.REMOVE_NEWLINES_ON_PASTE, true); + editor.getColorsScheme().setEditorFontSize(myComboBox.getFont().getSize()); } }; myEditor.getEditorComponent().setFontInheritedFromLAF(false); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java index a2bd211a6b22..fb5ddddb9d6a 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java @@ -53,21 +53,21 @@ public class GenericRepository extends BaseRepositoryImpl { @NonNls public static final String USERNAME = "username"; @NonNls public static final String PASSWORD = "password"; - public final FactoryVariable SERVER_URL_TEMPLATE_VARIABLE = new FactoryVariable(SERVER_URL) { + private final FactoryVariable myServerTemplateVariable = new FactoryVariable(SERVER_URL) { @NotNull @Override public String getValue() { return GenericRepository.this.getUrl(); } }; - public final FactoryVariable USERNAME_TEMPLATE_VARIABLE = new FactoryVariable(USERNAME) { + private final FactoryVariable myUserNameTemplateVariable = new FactoryVariable(USERNAME) { @NotNull @Override public String getValue() { return GenericRepository.this.getUsername(); } }; - public final FactoryVariable PASSWORD_TEMPLATE_VARIABLE = new FactoryVariable(PASSWORD, true) { + private final FactoryVariable myPasswordTemplateVariable = new FactoryVariable(PASSWORD, true) { @NotNull @Override public String getValue() { @@ -75,11 +75,9 @@ public class GenericRepository extends BaseRepositoryImpl { } }; - public final List PREDEFINED_TEMPLATE_VARIABLES = ContainerUtil.newSmartList( - SERVER_URL_TEMPLATE_VARIABLE, - USERNAME_TEMPLATE_VARIABLE, - PASSWORD_TEMPLATE_VARIABLE - ); + private final List myPredefinedTemplateVariables = Arrays.asList(myServerTemplateVariable, + myUserNameTemplateVariable, + myPasswordTemplateVariable); private String myLoginURL = ""; private String myTasksListUrl = ""; @@ -330,7 +328,7 @@ public class GenericRepository extends BaseRepositoryImpl { * Returns all template variables including both predefined and defined by user */ public List getAllTemplateVariables() { - return ContainerUtil.concat(PREDEFINED_TEMPLATE_VARIABLES, getTemplateVariables()); + return ContainerUtil.concat(myPredefinedTemplateVariables, getTemplateVariables()); } public void setTemplateVariables(final List templateVariables) { diff --git a/python/helpers/profiler/prof_data.py b/python/helpers/profiler/prof_data.py deleted file mode 100644 index d71ceae9bd4b..000000000000 --- a/python/helpers/profiler/prof_data.py +++ /dev/null @@ -1,11 +0,0 @@ -def copy_fields(obj, yappi_obj): - for k in yappi_obj._KEYS: - if k != 'children': - if hasattr(obj, k): - setattr(obj, k, getattr(yappi_obj, k)) - - if hasattr(yappi_obj, 'children'): - for o in getattr(yappi_obj, 'children'): - child = obj.children.add() - copy_fields(child, o) - diff --git a/python/helpers/profiler/prof_io.py b/python/helpers/profiler/prof_io.py index 6f7848babacc..72caf19c7e0b 100644 --- a/python/helpers/profiler/prof_io.py +++ b/python/helpers/profiler/prof_io.py @@ -3,10 +3,9 @@ import sys import time import traceback -from profiler_protocol_pb2 import ProfilerRequest - - -__author__ = 'traff' +from thrift import TSerialization +from thrift.protocol import TJSONProtocol, TBinaryProtocol +from profiler.ttypes import ProfilerRequest from prof_util import ProfDaemonThread @@ -21,7 +20,7 @@ def send_message(sock, message): to a socket, prepended by its length packed in 4 bytes (big endian). """ - s = message.SerializeToString() + s = TSerialization.serialize(message, TJSONProtocol.TJSONProtocolFactory()) packed_len = struct.pack('>L', len(s)) sock.sendall(packed_len + s) @@ -35,7 +34,8 @@ def get_message(sock, msgtype): msg_buf = socket_read_n(sock, msg_len) msg = msgtype() - msg.ParseFromString(msg_buf) + TSerialization.deserialize(msg, msg_buf, TJSONProtocol.TJSONProtocolFactory()) + return msg @@ -54,56 +54,13 @@ def socket_read_n(sock, n): return buf -class ProfWriter(ProfDaemonThread): +class ProfWriter(object): """ writer thread writes out the commands in an infinite loop """ def __init__(self, sock): - ProfDaemonThread.__init__(self) self.sock = sock - self.setName("profiler.Writer") - self.messageQueue = _queue.Queue() - if pydevd_vm_type.GetVmType() == 'python': - self.timeout = 0 - else: - self.timeout = 0.1 def addCommand(self, message): - """ message is NetCommand """ - if not self.killReceived: #we don't take new data after everybody die - self.messageQueue.put(message) - - def OnRun(self): - """ just loop and write responses """ - - get_has_timeout = sys.hexversion >= 0x02030000 # 2.3 onwards have it. - try: - while True: - try: - try: - if get_has_timeout: - message = self.messageQueue.get(1, 0.1) - else: - time.sleep(.01) - message = self.messageQueue.get(0) - except _queue.Empty: - if self.killReceived: - try: - self.sock.shutdown(SHUT_WR) - self.sock.close() - except: - pass - - return #break if queue is empty and killReceived - else: - continue - except: - return - - send_message(self.sock, message) - - time.sleep(self.timeout) - except Exception: - traceback.print_exc() - + send_message(self.sock, message) class ProfReader(ProfDaemonThread): """ reader thread reads and dispatches commands in an infinite loop """ diff --git a/python/helpers/profiler/prof_util.py b/python/helpers/profiler/prof_util.py index 03c15317112c..66e2e21282f8 100644 --- a/python/helpers/profiler/prof_util.py +++ b/python/helpers/profiler/prof_util.py @@ -1,6 +1,7 @@ __author__ = 'traff' import threading +import os class ProfDaemonThread(threading.Thread): def __init__(self): @@ -12,4 +13,14 @@ class ProfDaemonThread(threading.Thread): self.OnRun() def OnRun(self): - pass \ No newline at end of file + pass + +def generate_snapshot_filepath(basepath): + n = 0 + path = basepath + '.pstat' + while os.path.exists(path): + n+=1 + path = basepath + (str(n) if n>0 else '') + '.pstat' + + return path + diff --git a/python/helpers/profiler/profiler/ttypes.py b/python/helpers/profiler/profiler/ttypes.py index f025d36ff1aa..089481e53256 100644 --- a/python/helpers/profiler/profiler/ttypes.py +++ b/python/helpers/profiler/profiler/ttypes.py @@ -369,11 +369,20 @@ class Stats_Req: def __ne__(self, other): return not (self == other) -class StatsString_Req: +class SaveSnapshot_Req: + """ + Attributes: + - filepath + """ thrift_spec = ( + None, # 0 + (1, TType.STRING, 'filepath', None, None, ), # 1 ) + def __init__(self, filepath=None,): + self.filepath = filepath + def read(self, iprot): if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) @@ -383,6 +392,11 @@ class StatsString_Req: (fname, ftype, fid) = iprot.readFieldBegin() if ftype == TType.STOP: break + if fid == 1: + if ftype == TType.STRING: + self.filepath = iprot.readString(); + else: + iprot.skip(ftype) else: iprot.skip(ftype) iprot.readFieldEnd() @@ -392,16 +406,23 @@ class StatsString_Req: if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) return - oprot.writeStructBegin('StatsString_Req') + oprot.writeStructBegin('SaveSnapshot_Req') + if self.filepath is not None: + oprot.writeFieldBegin('filepath', TType.STRING, 1) + oprot.writeString(self.filepath) + oprot.writeFieldEnd() oprot.writeFieldStop() oprot.writeStructEnd() def validate(self): + if self.filepath is None: + raise TProtocol.TProtocolException(message='Required field filepath is unset!') return def __hash__(self): value = 17 + value = (value * 31) ^ hash(self.filepath) return value def __repr__(self): @@ -420,20 +441,20 @@ class ProfilerRequest: Attributes: - id - ystats - - ystats_string + - save_snapshot """ thrift_spec = ( None, # 0 (1, TType.I32, 'id', None, None, ), # 1 (2, TType.STRUCT, 'ystats', (Stats_Req, Stats_Req.thrift_spec), None, ), # 2 - (3, TType.STRUCT, 'ystats_string', (StatsString_Req, StatsString_Req.thrift_spec), None, ), # 3 + (3, TType.STRUCT, 'save_snapshot', (SaveSnapshot_Req, SaveSnapshot_Req.thrift_spec), None, ), # 3 ) - def __init__(self, id=None, ystats=None, ystats_string=None,): + def __init__(self, id=None, ystats=None, save_snapshot=None,): self.id = id self.ystats = ystats - self.ystats_string = ystats_string + self.save_snapshot = save_snapshot def read(self, iprot): if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: @@ -457,8 +478,8 @@ class ProfilerRequest: iprot.skip(ftype) elif fid == 3: if ftype == TType.STRUCT: - self.ystats_string = StatsString_Req() - self.ystats_string.read(iprot) + self.save_snapshot = SaveSnapshot_Req() + self.save_snapshot.read(iprot) else: iprot.skip(ftype) else: @@ -479,9 +500,9 @@ class ProfilerRequest: oprot.writeFieldBegin('ystats', TType.STRUCT, 2) self.ystats.write(oprot) oprot.writeFieldEnd() - if self.ystats_string is not None: - oprot.writeFieldBegin('ystats_string', TType.STRUCT, 3) - self.ystats_string.write(oprot) + if self.save_snapshot is not None: + oprot.writeFieldBegin('save_snapshot', TType.STRUCT, 3) + self.save_snapshot.write(oprot) oprot.writeFieldEnd() oprot.writeFieldStop() oprot.writeStructEnd() @@ -496,7 +517,7 @@ class ProfilerRequest: value = 17 value = (value * 31) ^ hash(self.id) value = (value * 31) ^ hash(self.ystats) - value = (value * 31) ^ hash(self.ystats_string) + value = (value * 31) ^ hash(self.save_snapshot) return value def __repr__(self): @@ -515,20 +536,20 @@ class ProfilerResponse: Attributes: - id - ystats - - ystats_string + - snapshot_filepath """ thrift_spec = ( None, # 0 (1, TType.I32, 'id', None, None, ), # 1 (2, TType.STRUCT, 'ystats', (Stats, Stats.thrift_spec), None, ), # 2 - (3, TType.STRING, 'ystats_string', None, None, ), # 3 + (3, TType.STRING, 'snapshot_filepath', None, None, ), # 3 ) - def __init__(self, id=None, ystats=None, ystats_string=None,): + def __init__(self, id=None, ystats=None, snapshot_filepath=None,): self.id = id self.ystats = ystats - self.ystats_string = ystats_string + self.snapshot_filepath = snapshot_filepath def read(self, iprot): if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: @@ -552,7 +573,7 @@ class ProfilerResponse: iprot.skip(ftype) elif fid == 3: if ftype == TType.STRING: - self.ystats_string = iprot.readString(); + self.snapshot_filepath = iprot.readString(); else: iprot.skip(ftype) else: @@ -573,9 +594,9 @@ class ProfilerResponse: oprot.writeFieldBegin('ystats', TType.STRUCT, 2) self.ystats.write(oprot) oprot.writeFieldEnd() - if self.ystats_string is not None: - oprot.writeFieldBegin('ystats_string', TType.STRING, 3) - oprot.writeString(self.ystats_string) + if self.snapshot_filepath is not None: + oprot.writeFieldBegin('snapshot_filepath', TType.STRING, 3) + oprot.writeString(self.snapshot_filepath) oprot.writeFieldEnd() oprot.writeFieldStop() oprot.writeStructEnd() @@ -590,7 +611,7 @@ class ProfilerResponse: value = 17 value = (value * 31) ^ hash(self.id) value = (value * 31) ^ hash(self.ystats) - value = (value * 31) ^ hash(self.ystats_string) + value = (value * 31) ^ hash(self.snapshot_filepath) return value def __repr__(self): diff --git a/python/helpers/profiler/run_profiler.py b/python/helpers/profiler/run_profiler.py index 4f9dff0a7faf..c0acc257916e 100644 --- a/python/helpers/profiler/run_profiler.py +++ b/python/helpers/profiler/run_profiler.py @@ -5,15 +5,18 @@ import time import sys import traceback import StringIO - -import yappi +import os from prof_io import ProfWriter, ProfReader from pydevd_utils import save_main_module import pydev_imports -from prof_data import copy_fields -from profiler_protocol_pb2 import ProfilerResponse, Stats +from prof_util import generate_snapshot_filepath +from thrift import TSerialization +from thrift.protocol import TJSONProtocol, TBinaryProtocol +from profiler.ttypes import ProfilerResponse + +base_snapshot_path = os.getenv('PYCHARM_SNAPSHOT_PATH') def StartClient(host, port): """ connects to a host/port """ @@ -39,7 +42,14 @@ def StartClient(host, port): class Profiler(object): def __init__(self): - pass + try: + import yappi_profiler + self.profiling_backend = yappi_profiler.YappiProfile() + print('Starting yappi profiler\n') + except ImportError: + import cProfile + self.profiling_backend = cProfile.Profile() + print('Starting cProfile profiler\n') def connect(self, host, port): s = StartClient(host, port) @@ -53,18 +63,15 @@ class Profiler(object): pass self.writer = ProfWriter(sock) self.reader = ProfReader(sock, self) - self.writer.start() self.reader.start() time.sleep(0.1) # give threads time to start def process(self, message): - if message.HasField('ystats_string'): - self.stats_string(message.id) - elif message.HasField('ystats'): - self.func_stats(message.id) + if hasattr(message, 'save_snapshot'): + self.save_snapshot(message.id, generate_snapshot_filepath(message.save_snapshot.filepath)) else: - raise AssertionError("malformed request") + raise AssertionError("Unknown request %s" % dir(message)) def run(self, file): m = save_main_module(file, 'run_profiler') @@ -78,32 +85,32 @@ class Profiler(object): pydev_imports.execfile(file, globals, globals) # execute the script - # self.stats_string() - - time.sleep(10) + self.stop_profiling() + self.save_snapshot(0, generate_snapshot_filepath(base_snapshot_path)) def start_profiling(self): - yappi.start(profile_threads=False) + self.profiling_backend.enable() - def stats_string(self, id): - output = StringIO.StringIO() - yappi.get_func_stats().print_all(out=output) - m = ProfilerResponse() - m.id = id - m.ystats_string = output.getvalue() - self.writer.addCommand(m) + def stop_profiling(self): + self.profiling_backend.disable() - def func_stats(self, id): - yfunc_stats = yappi.get_func_stats() - m = ProfilerResponse() - m.id = id - ystats = Stats() + def get_snapshot(self): + return self.profiling_backend.getstats() + + def dump_snapshot(self, filename): + self.profiling_backend.dump_stats(filename) + return filename + + def save_snapshot(self, id, filename): + self.stop_profiling() + filename = self.dump_snapshot(filename) + + m = ProfilerResponse(id=id, snapshot_filepath=filename) + + print('Snapshot saved to %s' % filename) - for fstat in yfunc_stats: - func_stat = ystats.func_stats.add() - copy_fields(func_stat, fstat) - m.ystats.CopyFrom(ystats) self.writer.addCommand(m) + self.start_profiling() if __name__ == '__main__': diff --git a/python/helpers/profiler/yappi_profiler.py b/python/helpers/profiler/yappi_profiler.py new file mode 100644 index 000000000000..c1024c4b0e9d --- /dev/null +++ b/python/helpers/profiler/yappi_profiler.py @@ -0,0 +1,37 @@ +import yappi + +class YappiProfile(object): + """ Wrapper class that represents Yappi profiling backend with API matching + the cProfile. + """ + def __init__(self): + self.stats = None + + def runcall(self, func, *args, **kw): + self.enable() + try: + return func(*args, **kw) + finally: + self.disable() + + def enable(self): + yappi.start() + + def disable(self): + yappi.stop() + + def create_stats(self): + self.stats = yappi.convert2pstats(yappi.get_func_stats()).stats + + def getstats(self): + if self.stats is None: + self.create_stats() + + return self.stats + + def dump_stats(self, file): + import marshal + f = open(file, 'wb') + marshal.dump(self.getstats(), f) + f.close() + diff --git a/xml/impl/resources/liveTemplates/zen_html.xml b/xml/impl/resources/liveTemplates/zen_html.xml index f04edf4115de..f6dbb138c121 100644 --- a/xml/impl/resources/liveTemplates/zen_html.xml +++ b/xml/impl/resources/liveTemplates/zen_html.xml @@ -115,7 +115,7 @@