summaryrefslogtreecommitdiff
path: root/platform/lang-impl
diff options
context:
space:
mode:
Diffstat (limited to 'platform/lang-impl')
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java3
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form44
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java120
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java36
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.form35
-rw-r--r--platform/lang-impl/src/com/intellij/application/options/editor/EditorTabsConfigurable.java26
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java11
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java3
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java47
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java2
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java2
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java22
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java4
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java90
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java9
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java45
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java256
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java5
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java6
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java7
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java (renamed from platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java)66
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java22
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java19
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java54
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java35
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java39
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java83
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java18
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java6
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java8
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java12
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java58
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java42
-rw-r--r--platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java2
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java2
-rw-r--r--platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java63
-rw-r--r--platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java47
-rw-r--r--platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java6
-rw-r--r--platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java10
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java76
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java9
-rw-r--r--platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java6
-rw-r--r--platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java11
-rw-r--r--platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java6
-rw-r--r--platform/lang-impl/src/com/intellij/find/FindSettings.java9
-rw-r--r--platform/lang-impl/src/com/intellij/find/FindUtil.java4
-rw-r--r--platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java38
-rw-r--r--platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java38
-rw-r--r--platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java38
-rw-r--r--platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java4
-rw-r--r--platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java4
-rw-r--r--platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java11
-rw-r--r--platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java11
-rw-r--r--platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java5
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindDialog.java91
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java58
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java11
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java204
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java10
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java47
-rw-r--r--platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java39
-rw-r--r--platform/lang-impl/src/com/intellij/formatting/FormatterEx.java11
-rw-r--r--platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java53
-rw-r--r--platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java33
-rw-r--r--platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java4
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java14
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java279
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java5
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java5
-rw-r--r--platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java10
-rw-r--r--platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java23
-rw-r--r--platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java7
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java25
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java144
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java2
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java1
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java7
-rw-r--r--platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java27
-rw-r--r--platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java8
-rw-r--r--platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java22
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java7
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java9
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java21
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java10
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java8
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java14
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java150
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java6
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java211
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java41
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java7
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java41
-rw-r--r--platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java21
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java117
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java209
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java4
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java6
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java58
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java62
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java60
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java121
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java109
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java18
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java19
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java70
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java19
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java32
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java94
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java31
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java40
-rw-r--r--platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java22
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java133
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java4
-rw-r--r--platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java71
-rw-r--r--platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java2
-rw-r--r--platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java1
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java2
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java2
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java51
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java2
-rw-r--r--platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java6
-rw-r--r--platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java18
-rw-r--r--platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java58
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java4
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java5
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java3
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java4
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java3
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java4
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java3
-rw-r--r--platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java4
-rw-r--r--platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java52
132 files changed, 3107 insertions, 1737 deletions
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java
index f978d5f6dcdb..59736bc0e4b2 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTableWithPreviewPanel.java
@@ -18,6 +18,7 @@ package com.intellij.application.options.codeStyle;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.codeStyle.CustomCodeStyleSettings;
import com.intellij.ui.SpeedSearchComparator;
import com.intellij.ui.TreeTableSpeedSearch;
@@ -378,7 +379,7 @@ public abstract class OptionTableWithPreviewPanel extends MultilanguageCodeStyle
this.groupName = groupName;
try {
- Class styleSettingsClass = clazz == null ? CodeStyleSettings.class : clazz;
+ Class styleSettingsClass = clazz == null ? CommonCodeStyleSettings.class : clazz;
this.field = styleSettingsClass.getField(fieldName);
}
catch (NoSuchFieldException e) {
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form
new file mode 100644
index 000000000000..67f579a77ff5
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.form
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.application.options.codeStyle.RightMarginForm">
+ <grid id="27dc6" binding="myTopPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="12cf8" class="com.intellij.ui.components.JBLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/ApplicationBundle" key="editbox.right.margin.columns"/>
+ </properties>
+ </component>
+ <vspacer id="1265c">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <component id="78fe" class="javax.swing.JTextField" binding="myRightMarginField">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="50" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <horizontalAlignment value="2"/>
+ </properties>
+ </component>
+ <component id="5ef52" class="javax.swing.JCheckBox" binding="myDefaultGeneralCheckBox" default-binding="true">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/ApplicationBundle" key="settings.code.style.default.general"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java
new file mode 100644
index 000000000000..70c747dc11ca
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/RightMarginForm.java
@@ -0,0 +1,120 @@
+/*
+ * 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.application.options.codeStyle;
+
+import com.intellij.lang.Language;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+/**
+ * Can be used for languages which do not use standard "Wrapping and Braces" panel.
+ * <p>
+ * <strong>Note</strong>: besides adding the panel to UI it is necessary to make sure that language's own
+ * <code>LanguageCodeStyleSettingsProvider</code> explicitly supports RIGHT_MARGIN field in <code>customizeSettings()</code>
+ * method as shown below:
+ * <pre>
+ * public void customizeSettings(...) {
+ * if (settingsType == SettingsType.WRAPPING_AND_BRACES_SETTINGS) {
+ * consumer.showStandardOptions("RIGHT_MARGIN");
+ * }
+ * }
+ * </pre>
+ * @author Rustam Vishnyakov
+ */
+public class RightMarginForm {
+ private JTextField myRightMarginField;
+ private JCheckBox myDefaultGeneralCheckBox;
+ private JPanel myTopPanel;
+ private final Language myLanguage;
+ private final int myDefaultRightMargin;
+
+ public RightMarginForm(@NotNull Language language, @NotNull CodeStyleSettings settings) {
+ myLanguage = language;
+ myDefaultRightMargin = settings.RIGHT_MARGIN;
+ myDefaultGeneralCheckBox.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ if (myDefaultGeneralCheckBox.isSelected()) {
+ myRightMarginField.setText(Integer.toString(myDefaultRightMargin));
+ myRightMarginField.setEnabled(false);
+ }
+ else {
+ myRightMarginField.setEnabled(true);
+ }
+ }
+ });
+ }
+
+ public void reset(@NotNull CodeStyleSettings settings) {
+ CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage);
+ if (langSettings != settings && langSettings.RIGHT_MARGIN >= 0) {
+ myDefaultGeneralCheckBox.setSelected(false);
+ myRightMarginField.setText(Integer.toString(langSettings.RIGHT_MARGIN));
+ }
+ else {
+ myDefaultGeneralCheckBox.setSelected(true);
+ myRightMarginField.setText(Integer.toString(settings.RIGHT_MARGIN));
+ if (langSettings == settings) {
+ myDefaultGeneralCheckBox.setEnabled(false);
+ myRightMarginField.setEnabled(false);
+ }
+ }
+ }
+
+ public void apply(@NotNull CodeStyleSettings settings) {
+ CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage);
+ if (langSettings != settings) {
+ if (myDefaultGeneralCheckBox.isSelected()) {
+ langSettings.RIGHT_MARGIN = -1;
+ }
+ else {
+ langSettings.RIGHT_MARGIN = getFieldRightMargin(settings.RIGHT_MARGIN);
+ }
+ }
+ }
+
+ public boolean isModified(@NotNull CodeStyleSettings settings) {
+ CommonCodeStyleSettings langSettings = settings.getCommonSettings(myLanguage);
+ if (myDefaultGeneralCheckBox.isSelected()) {
+ return langSettings.RIGHT_MARGIN >= 0;
+ }
+ else {
+ return langSettings.RIGHT_MARGIN != getFieldRightMargin(settings.RIGHT_MARGIN);
+ }
+ }
+
+ private int getFieldRightMargin(int fallBackValue) {
+ String strValue = myRightMarginField.getText();
+ if (!strValue.trim().isEmpty()) {
+ try {
+ return Integer.parseInt(strValue);
+ }
+ catch (NumberFormatException e) {
+ myRightMarginField.setText(Integer.toString(fallBackValue));
+ }
+ }
+ return fallBackValue;
+ }
+
+ public JPanel getTopPanel() {
+ return myTopPanel;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java
index fa14958132d0..145ae1094e0b 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/match/ArrangementMatchingRulesControl.java
@@ -165,7 +165,7 @@ public class ArrangementMatchingRulesControl extends JBTable {
}
final List<ArrangementSectionRule> result = ContainerUtil.newArrayList();
- final List<StdArrangementMatchRule> currentRules = ContainerUtil.newArrayList();
+ final List<StdArrangementMatchRule> buffer = ContainerUtil.newArrayList();
String currentSectionStart = null;
for (int i = 0; i < getModel().getSize(); i++) {
Object element = getModel().getElementAt(i);
@@ -174,15 +174,12 @@ public class ArrangementMatchingRulesControl extends JBTable {
mySectionRuleManager == null ? null : mySectionRuleManager.getSectionRuleData((StdArrangementMatchRule)element);
if (sectionRule != null) {
if (sectionRule.isSectionStart()) {
- if (currentSectionStart != null) {
- result.add(ArrangementSectionRule.create(currentSectionStart, null, currentRules));
- currentRules.clear();
- }
+ appendBufferedSectionRules(result, buffer, currentSectionStart);
currentSectionStart = sectionRule.getText();
}
else {
- result.add(ArrangementSectionRule.create(StringUtil.notNullize(currentSectionStart), sectionRule.getText(), currentRules));
- currentRules.clear();
+ result.add(ArrangementSectionRule.create(StringUtil.notNullize(currentSectionStart), sectionRule.getText(), buffer));
+ buffer.clear();
currentSectionStart = null;
}
}
@@ -190,17 +187,34 @@ public class ArrangementMatchingRulesControl extends JBTable {
result.add(ArrangementSectionRule.create((StdArrangementMatchRule)element));
}
else {
- currentRules.add((StdArrangementMatchRule)element);
+ buffer.add((StdArrangementMatchRule)element);
}
}
}
- if (currentSectionStart != null) {
- result.add(ArrangementSectionRule.create(currentSectionStart, null, currentRules));
- }
+ appendBufferedSectionRules(result, buffer, currentSectionStart);
return result;
}
+ private static void appendBufferedSectionRules(@NotNull List<ArrangementSectionRule> result,
+ @NotNull List<StdArrangementMatchRule> buffer,
+ @Nullable String currentSectionStart) {
+ if (currentSectionStart == null) {
+ return;
+ }
+
+ if (buffer.isEmpty()) {
+ result.add(ArrangementSectionRule.create(currentSectionStart, null));
+ }
+ else {
+ result.add(ArrangementSectionRule.create(currentSectionStart, null, buffer.get(0)));
+ for (int j = 1; j < buffer.size(); j++) {
+ result.add(ArrangementSectionRule.create(buffer.get(j)));
+ }
+ buffer.clear();
+ }
+ }
+
@Override
protected void processMouseEvent(MouseEvent e) {
int id = e.getID();
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 9872c7c624aa..db23ce17b2c3 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
@@ -3,7 +3,7 @@
<grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <xy x="20" y="20" width="500" height="527"/>
+ <xy x="20" y="20" width="500" height="585"/>
</constraints>
<properties/>
<border type="none"/>
@@ -108,7 +108,7 @@
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
- <grid id="eb8d0" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="10">
+ <grid id="eb8d0" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="10">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -119,7 +119,7 @@
</clientProperties>
<border type="none" title-resource-bundle="messages/ApplicationBundle" title-key="group.tab.closing.policy"/>
<children>
- <grid id="5a5a7" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="5a5a7" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -129,7 +129,9 @@
<children>
<component id="527a6" class="javax.swing.JLabel">
<constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="60" height="27"/>
+ </grid>
</constraints>
<properties>
<text resource-bundle="messages/ApplicationBundle" key="editbox.tab.limit"/>
@@ -138,19 +140,38 @@
<component id="16477" class="javax.swing.JTextField" binding="myEditorTabLimitField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false">
- <preferred-size width="30" height="-1"/>
+ <preferred-size width="30" height="27"/>
</grid>
</constraints>
<properties>
<text value="15"/>
</properties>
</component>
+ <component id="2479d" class="javax.swing.JLabel">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/ApplicationBundle" key="editbox.tab.title.limit"/>
+ </properties>
+ </component>
+ <component id="3499c" class="javax.swing.JTextField" binding="myTabTitleLimitField">
+ <constraints>
+ <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="30" height="27"/>
+ </grid>
+ </constraints>
+ <properties>
+ <columns value="2"/>
+ <text value="30"/>
+ </properties>
+ </component>
</children>
</grid>
<grid id="9b723" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -184,7 +205,7 @@
<grid id="611cc" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="2">
<margin top="10" left="0" bottom="0" right="0"/>
<constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
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 4e1de817255a..35a34085d035 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
@@ -45,6 +45,7 @@ public class EditorTabsConfigurable implements EditorOptionsProvider {
private JCheckBox myShowCloseButtonOnCheckBox;
private JCheckBox myShowDirectoryInTabCheckBox;
private JRadioButton myActivateRightNeighbouringTabRadioButton;
+ private JTextField myTabTitleLimitField;
public EditorTabsConfigurable() {
myEditorTabPlacement.setModel(new DefaultComboBoxModel(new Object[]{
@@ -119,6 +120,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));
+ myTabTitleLimitField.setText(Integer.toString(uiSettings.EDITOR_TAB_TITLE_LIMIT));
myShowCloseButtonOnCheckBox.setSelected(uiSettings.SHOW_CLOSE_BUTTON);
if (uiSettings.CLOSE_NON_MODIFIED_FILES_FIRST) {
@@ -171,14 +173,29 @@ public class EditorTabsConfigurable implements EditorOptionsProvider {
uiSettings.ACTIVATE_RIGHT_EDITOR_ON_CLOSE = myActivateRightNeighbouringTabRadioButton.isSelected();
String temp = myEditorTabLimitField.getText();
- if(temp.trim().length() > 0){
+ if (temp.trim().length() > 0) {
try {
int newEditorTabLimit = Integer.parseInt(temp);
- if(newEditorTabLimit>0&&newEditorTabLimit!=uiSettings.EDITOR_TAB_LIMIT){
- uiSettings.EDITOR_TAB_LIMIT=newEditorTabLimit;
+ if (newEditorTabLimit > 0 && newEditorTabLimit != uiSettings.EDITOR_TAB_LIMIT) {
+ uiSettings.EDITOR_TAB_LIMIT = newEditorTabLimit;
uiSettingsChanged = true;
}
- }catch (NumberFormatException ignored){}
+ }
+ catch (NumberFormatException ignored) {
+ }
+ }
+ temp = myTabTitleLimitField.getText();
+ if (temp.trim().length() > 0) {
+ try {
+ int newTabTitleLimit = Integer.parseInt(temp);
+ newTabTitleLimit = Math.max(25, Math.min(100, newTabTitleLimit));
+ if (newTabTitleLimit != uiSettings.EDITOR_TAB_TITLE_LIMIT){
+ uiSettings.EDITOR_TAB_TITLE_LIMIT = newTabTitleLimit;
+ uiSettingsChanged = true;
+ }
+ }
+ catch (NumberFormatException ignored) {
+ }
}
if(uiSettingsChanged){
uiSettings.fireUISettingsChanged();
@@ -191,6 +208,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(myTabTitleLimitField, uiSettings.EDITOR_TAB_TITLE_LIMIT);
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/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
index bf77a3022a0e..af6bbdc931ca 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java
@@ -289,7 +289,16 @@ public class FormatChangedTextUtil {
}
try {
- List<Range> changedRanges = new RangesBuilder(document, documentFromVcs).getRanges();
+ List<Range> changedRanges;
+
+ LineStatusTracker tracker = LineStatusTrackerManager.getInstance(project).getLineStatusTracker(document);
+ if (tracker != null) {
+ changedRanges = tracker.getRanges();
+ }
+ else {
+ changedRanges = new RangesBuilder(document, documentFromVcs).getRanges();
+ }
+
return getChangedTextRanges(document, changedRanges);
}
catch (FilesTooBigForDiffException e) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
index 4966a9466a26..8ec833e8258b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
@@ -79,9 +79,6 @@ public class ReformatCodeAction extends AnAction implements DumbAware {
PsiDocumentManager.getInstance(project).commitAllDocuments();
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
- if (files == null) {
- return;
- }
PsiFile file = null;
final PsiDirectory dir;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
index e0a3be5f423d..fcb080dcd277 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
@@ -71,6 +71,8 @@ import java.util.concurrent.atomic.AtomicReference;
public class CodeCompletionHandlerBase {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.completion.CodeCompletionHandlerBase");
+ private static final Key<Boolean> CARET_PROCESSED = Key.create("CodeCompletionHandlerBase.caretProcessed");
+
@NotNull private final CompletionType myCompletionType;
final boolean invokedExplicitly;
final boolean synchronous;
@@ -108,6 +110,13 @@ public class CodeCompletionHandlerBase {
}
public final void invokeCompletion(@NotNull final Project project, @NotNull final Editor editor, int time, boolean hasModifiers, boolean restarted) {
+ clearCaretMarkers(editor);
+ invokeCompletion(project, editor, time, hasModifiers, restarted, editor.getCaretModel().getPrimaryCaret());
+ }
+
+ public final void invokeCompletion(@NotNull final Project project, @NotNull final Editor editor, int time, boolean hasModifiers, boolean restarted, @NotNull final Caret caret) {
+ markCaretAsProcessed(caret);
+
if (invokedExplicitly) {
CompletionLookupArranger.applyLastCompletionStatisticsUpdate();
}
@@ -162,12 +171,12 @@ public class CodeCompletionHandlerBase {
PsiDocumentManager.getInstance(project).commitAllDocuments();
CompletionAssertions.checkEditorValid(editor);
- final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
+ final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(caret, project);
assert psiFile != null : "no PSI file: " + FileDocumentManager.getInstance().getFile(editor.getDocument());
psiFile.putUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING, Boolean.TRUE);
CompletionAssertions.assertCommitSuccessful(editor, psiFile);
- initializationContext[0] = runContributorsBeforeCompletion(editor, psiFile, invocationCount);
+ initializationContext[0] = runContributorsBeforeCompletion(editor, psiFile, invocationCount, caret);
}
};
ApplicationManager.getApplication().runWriteAction(runnable);
@@ -186,9 +195,9 @@ public class CodeCompletionHandlerBase {
insertDummyIdentifier(initializationContext[0], hasModifiers, invocationCount);
}
- private CompletionInitializationContext runContributorsBeforeCompletion(Editor editor, PsiFile psiFile, int invocationCount) {
+ private CompletionInitializationContext runContributorsBeforeCompletion(Editor editor, PsiFile psiFile, int invocationCount, Caret caret) {
final Ref<CompletionContributor> current = Ref.create(null);
- CompletionInitializationContext context = new CompletionInitializationContext(editor, psiFile, myCompletionType, invocationCount) {
+ CompletionInitializationContext context = new CompletionInitializationContext(editor, caret, psiFile, myCompletionType, invocationCount) {
CompletionContributor dummyIdentifierChanger;
@Override
@@ -400,8 +409,15 @@ public class CodeCompletionHandlerBase {
final LookupElement[] items, boolean hasModifiers) {
if (items.length == 0) {
LookupManager.getInstance(indicator.getProject()).hideActiveLookup();
- indicator.handleEmptyLookup(true);
- checkNotSync(indicator, items);
+
+ Caret nextCaret = getNextCaretToProcess(indicator.getEditor());
+ if (nextCaret != null) {
+ invokeCompletion(indicator.getProject(), indicator.getEditor(), indicator.getParameters().getInvocationCount(), hasModifiers, false, nextCaret);
+ }
+ else {
+ indicator.handleEmptyLookup(true);
+ checkNotSync(indicator, items);
+ }
return;
}
@@ -866,4 +882,23 @@ public class CodeCompletionHandlerBase {
}
};
}
+
+ private static void clearCaretMarkers(@NotNull Editor editor) {
+ for (Caret caret : editor.getCaretModel().getAllCarets()) {
+ caret.putUserData(CARET_PROCESSED, null);
+ }
+ }
+
+ private static void markCaretAsProcessed(@NotNull Caret caret) {
+ caret.putUserData(CARET_PROCESSED, Boolean.TRUE);
+ }
+
+ private static Caret getNextCaretToProcess(@NotNull Editor editor) {
+ for (Caret caret : editor.getCaretModel().getAllCarets()) {
+ if (caret.getUserData(CARET_PROCESSED) == null) {
+ return caret;
+ }
+ }
+ return null;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
index 8560129194f1..0321191294c5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
@@ -73,7 +73,7 @@ public class InjectedGeneralHighlightingPass extends GeneralHighlightingPass imp
@Override
protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
- if (!Registry.is("editor.injected.highlighting.enabled", true)) return;
+ if (!Registry.is("editor.injected.highlighting.enabled")) return;
final Set<HighlightInfo> gotHighlights = new THashSet<HighlightInfo>(100);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java
index 9211bead784b..6ff242108eed 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WolfHighlightingPass.java
@@ -38,7 +38,7 @@ class WolfHighlightingPass extends ProgressableTextEditorHighlightingPass implem
@Override
protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
- if (!Registry.is("wolf.the.problem.solver", true)) return;
+ if (!Registry.is("wolf.the.problem.solver")) return;
final WolfTheProblemSolver solver = WolfTheProblemSolver.getInstance(myProject);
if (solver instanceof WolfTheProblemSolverImpl) {
((WolfTheProblemSolverImpl)solver).startCheckingIfVincentSolvedProblemsYet(progress, this);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
index c27ce400049e..05a1e01c6aa1 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
@@ -261,10 +261,20 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
}
public void showJavaDocInfo(final Editor editor, @Nullable final PsiFile file, boolean requestFocus) {
- showJavaDocInfo(editor, file, requestFocus, true);
+ showJavaDocInfo(editor, file, requestFocus, null);
}
- private void showJavaDocInfo(final Editor editor, @Nullable final PsiFile file, boolean requestFocus, final boolean autoupdate) {
+ public void showJavaDocInfo(final Editor editor,
+ @Nullable final PsiFile file,
+ boolean requestFocus,
+ final Runnable closeCallback) {
+ showJavaDocInfo(editor, file, requestFocus, true, closeCallback);
+ }
+
+ private void showJavaDocInfo(final Editor editor,
+ @Nullable final PsiFile file,
+ boolean requestFocus,
+ final boolean autoupdate, @Nullable final Runnable closeCallback) {
myEditor = editor;
final Project project = getProject(file);
PsiDocumentManager.getInstance(project).commitAllDocuments();
@@ -314,7 +324,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
return;
}
if (lookupIteObject instanceof PsiElement) {
- doShowJavaDocInfo((PsiElement)lookupIteObject, false, this, originalElement, autoupdate);
+ doShowJavaDocInfo((PsiElement)lookupIteObject, false, this, originalElement, autoupdate, closeCallback);
return;
}
@@ -337,12 +347,12 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
}
}
else {
- doShowJavaDocInfo(element, false, this, originalElement, autoupdate);
+ doShowJavaDocInfo(element, false, this, originalElement, autoupdate, closeCallback);
}
}
};
- doShowJavaDocInfo(element, requestFocus, updateProcessor, originalElement, autoupdate);
+ doShowJavaDocInfo(element, requestFocus, updateProcessor, originalElement, autoupdate, closeCallback);
}
public PsiElement findTargetElement(Editor editor, PsiFile file) {
@@ -969,7 +979,7 @@ public class DocumentationManager extends DockablePopupManager<DocumentationComp
@Override
protected void doUpdateComponent(Editor editor, PsiFile psiFile) {
- showJavaDocInfo(editor, psiFile, false, true);
+ showJavaDocInfo(editor, psiFile, false, true, null);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
index 2a46c08fc2dd..b738bafb038a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
@@ -19,12 +19,12 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actions.CopyAction;
import com.intellij.openapi.editor.actions.EditorActionUtil;
import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.impl.EditorCopyPasteHelperImpl;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.Project;
@@ -92,7 +92,7 @@ public class CopyHandler extends EditorActionHandler {
}
String text = editor.getCaretModel().supportsMultipleCarets()
- ? CopyPasteSupport.getSelectedTextForClipboard(editor, transferableDatas)
+ ? EditorCopyPasteHelperImpl.getSelectedTextForClipboard(editor, transferableDatas)
: selectionModel.getSelectedText();
String rawText = TextBlockTransferable.convertLineSeparators(text, "\n", transferableDatas);
String escapedText = null;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java
index 345cb80bae69..17916e008501 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/IndentingBackspaceHandler.java
@@ -17,15 +17,22 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeStyle.CodeStyleFacade;
+import com.intellij.formatting.*;
+import com.intellij.lang.LanguageFormatting;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
@@ -36,40 +43,75 @@ import org.jetbrains.annotations.NotNull;
public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
private static final Logger LOG = Logger.getInstance(IndentingBackspaceHandler.class);
+ private boolean isApplicable;
private boolean caretWasAtLineStart;
+ private String precalculatedSpacing;
@Override
public void beforeCharDeleted(char c, PsiFile file, Editor editor) {
- caretWasAtLineStart = editor.getCaretModel().getLogicalPosition().column == 0;
- }
-
- @Override
- public boolean charDeleted(char c, PsiFile file, Editor editor) {
if (CodeInsightSettings.getInstance().SMART_BACKSPACE != CodeInsightSettings.AUTOINDENT || !StringUtil.isWhiteSpace(c)) {
- return false;
+ isApplicable = false;
+ return;
}
LanguageCodeStyleSettingsProvider codeStyleSettingsProvider = LanguageCodeStyleSettingsProvider.forLanguage(file.getLanguage());
if (codeStyleSettingsProvider != null && codeStyleSettingsProvider.isIndentBasedLanguageSemantics()) {
+ isApplicable = false;
+ return;
+ }
+ Document document = editor.getDocument();
+ CharSequence charSequence = document.getCharsSequence();
+ CaretModel caretModel = editor.getCaretModel();
+ int caretOffset = caretModel.getOffset();
+ LogicalPosition pos = caretModel.getLogicalPosition();
+ isApplicable = true;
+ caretWasAtLineStart = pos.column == 0;
+ precalculatedSpacing = null;
+ if (caretWasAtLineStart && pos.line > 0 && caretOffset < charSequence.length() && !StringUtil.isWhiteSpace(charSequence.charAt(caretOffset))) {
+ int prevLineEnd = document.getLineEndOffset(pos.line - 1);
+ if (prevLineEnd > 0 && !StringUtil.isWhiteSpace(charSequence.charAt(prevLineEnd - 1))) {
+ PsiDocumentManager.getInstance(file.getProject()).commitDocument(document);
+ precalculatedSpacing = getSpacing(file, caretOffset);
+ }
+ }
+ }
+
+ @Override
+ public boolean charDeleted(char c, PsiFile file, Editor editor) {
+ if (!isApplicable) {
return false;
}
+ Project project = file.getProject();
Document document = editor.getDocument();
+ CaretModel caretModel = editor.getCaretModel();
- int caretOffset = editor.getCaretModel().getOffset();
+ int caretOffset = caretModel.getOffset();
int offset = CharArrayUtil.shiftForward(document.getCharsSequence(), caretOffset, " \t");
int beforeWhitespaceOffset = CharArrayUtil.shiftBackward(document.getCharsSequence(), offset - 1, " \t") + 1;
- LogicalPosition logicalPosition = caretOffset < offset ? editor.offsetToLogicalPosition(offset) : editor.getCaretModel().getLogicalPosition();
+ LogicalPosition logicalPosition = caretOffset < offset ? editor.offsetToLogicalPosition(offset) : caretModel.getLogicalPosition();
int lineStartOffset = document.getLineStartOffset(logicalPosition.line);
if (lineStartOffset < beforeWhitespaceOffset) {
- if (caretWasAtLineStart && beforeWhitespaceOffset < offset) {
- document.deleteString(beforeWhitespaceOffset, offset);
- return true;
+ if (caretWasAtLineStart && beforeWhitespaceOffset <= offset) {
+ String spacing;
+ if (precalculatedSpacing == null) {
+ PsiDocumentManager.getInstance(project).commitDocument(document);
+ spacing = getSpacing(file, offset);
+ }
+ else {
+ spacing = precalculatedSpacing;
+ }
+ if (beforeWhitespaceOffset < offset || !spacing.isEmpty()) {
+ document.replaceString(beforeWhitespaceOffset, offset, spacing);
+ caretModel.moveToOffset(beforeWhitespaceOffset + spacing.length());
+ return true;
+ }
}
return false;
}
- CodeStyleFacade codeStyleFacade = CodeStyleFacade.getInstance(editor.getProject());
- String indent = codeStyleFacade.getLineIndent(document, lineStartOffset);
+ PsiDocumentManager.getInstance(project).commitDocument(document);
+ CodeStyleFacade codeStyleFacade = CodeStyleFacade.getInstance(project);
+ String indent = codeStyleFacade.getLineIndent(document, offset);
if (indent == null) {
return false;
}
@@ -79,7 +121,7 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
if (logicalPosition.column == targetColumn) {
if (caretOffset < offset) {
- editor.getCaretModel().moveToLogicalPosition(logicalPosition);
+ caretModel.moveToLogicalPosition(logicalPosition);
return true;
}
return false;
@@ -87,7 +129,7 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
if (caretWasAtLineStart || logicalPosition.column > targetColumn) {
document.replaceString(lineStartOffset, offset, indent);
- editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(logicalPosition.line, targetColumn));
+ caretModel.moveToLogicalPosition(new LogicalPosition(logicalPosition.line, targetColumn));
return true;
}
@@ -100,12 +142,13 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
int targetOffset = CharArrayUtil.shiftBackward(document.getCharsSequence(), prevLineEndOffset - 1, " \t") + 1;
if (prevLineStartOffset < targetOffset) {
- document.deleteString(targetOffset, offset);
- editor.getCaretModel().moveToOffset(targetOffset);
+ String spacing = getSpacing(file, offset);
+ document.replaceString(targetOffset, offset, spacing);
+ caretModel.moveToOffset(targetOffset + spacing.length());
}
else {
document.replaceString(prevLineStartOffset, offset, indent);
- editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(logicalPosition.line - 1, targetColumn));
+ caretModel.moveToLogicalPosition(new LogicalPosition(logicalPosition.line - 1, targetColumn));
}
return true;
}
@@ -132,4 +175,15 @@ public class IndentingBackspaceHandler extends BackspaceHandlerDelegate {
}
return width;
}
+
+ private static String getSpacing(PsiFile file, int offset) {
+ FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
+ if (builder == null) {
+ return "";
+ }
+ CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(file.getProject());
+ FormattingModel model = builder.createModel(file, settings);
+ int spacing = FormatterEx.getInstance().getSpacingForBlockAtOffset(model, offset);
+ return StringUtil.repeatSymbol(' ', spacing);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
index bb21eac69ecd..ba4768f73099 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
@@ -148,14 +148,17 @@ public class TypedHandler extends TypedActionHandlerBase {
return;
}
+ final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project);
+ final Document originalDocument = originalEditor.getDocument();
originalEditor.getCaretModel().runForEachCaret(new CaretAction() {
@Override
public void perform(Caret caret) {
- PsiDocumentManager.getInstance(project)
- .doPostponedOperationsAndUnblockDocument(originalEditor.getDocument()); // to clean up after previous caret processing
+ if (psiDocumentManager.isDocumentBlockedByPsi(originalDocument)) {
+ psiDocumentManager.doPostponedOperationsAndUnblockDocument(originalDocument); // to clean up after previous caret processing
+ }
Editor editor = injectedEditorIfCharTypedIsSignificant(charTyped, originalEditor, originalFile);
- PsiFile file = editor == originalEditor ? originalFile : PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+ PsiFile file = editor == originalEditor ? originalFile : psiDocumentManager.getPsiFile(editor.getDocument());
final TypedHandlerDelegate[] delegates = Extensions.getExtensions(TypedHandlerDelegate.EP_NAME);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
index 3a1f04b80414..9a71909fcca8 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java
@@ -372,31 +372,34 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable,
checkValid();
CollectionListModel<LookupElement> listModel = getListModel();
- synchronized (myList) {
- Pair<List<LookupElement>, Integer> pair = myPresentableArranger.arrangeItems(this, onExplicitAction || reused);
- List<LookupElement> items = pair.first;
- Integer toSelect = pair.second;
- if (toSelect == null || toSelect < 0 || items.size() > 0 && toSelect >= items.size()) {
- LOG.error("Arranger " + myPresentableArranger + " returned invalid selection index=" + toSelect + "; items=" + items);
- }
-
- myOffsets.checkMinPrefixLengthChanges(items, this);
- List<LookupElement> oldModel = listModel.toList();
- listModel.removeAll();
- if (!items.isEmpty()) {
- listModel.add(items);
- }
- else {
- addEmptyItem(listModel);
- }
+ Pair<List<LookupElement>, Integer> pair;
+ synchronized (myList) {
+ pair = myPresentableArranger.arrangeItems(this, onExplicitAction || reused);
+ }
+
+ List<LookupElement> items = pair.first;
+ Integer toSelect = pair.second;
+ if (toSelect == null || toSelect < 0 || items.size() > 0 && toSelect >= items.size()) {
+ LOG.error("Arranger " + myPresentableArranger + " returned invalid selection index=" + toSelect + "; items=" + items);
+ toSelect = 0;
+ }
- updateListHeight(listModel);
+ myOffsets.checkMinPrefixLengthChanges(items, this);
+ List<LookupElement> oldModel = listModel.toList();
- myList.setSelectedIndex(toSelect);
- return !ContainerUtil.equalsIdentity(oldModel, items);
+ listModel.removeAll();
+ if (!items.isEmpty()) {
+ listModel.add(items);
}
+ else {
+ addEmptyItem(listModel);
+ }
+
+ updateListHeight(listModel);
+ myList.setSelectedIndex(toSelect);
+ return !ContainerUtil.equalsIdentity(oldModel, items);
}
private boolean isSelectionVisible() {
@@ -566,7 +569,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable,
public void perform(Caret caret) {
EditorModificationUtil.deleteSelectedText(hostEditor);
final int caretOffset = hostEditor.getCaretModel().getOffset();
- int lookupStart = caretOffset - prefix;
+ int lookupStart = Math.max(caretOffset - prefix, 0);
int len = hostEditor.getDocument().getTextLength();
LOG.assertTrue(lookupStart >= 0 && lookupStart <= len,
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
index 3c0e84a11656..3617c944e888 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
@@ -19,30 +19,46 @@ package com.intellij.codeInsight.navigation;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.ide.util.EditSourceUtil;
import com.intellij.ide.util.PsiElementListCellRenderer;
+import com.intellij.navigation.GotoRelatedItem;
+import com.intellij.navigation.GotoRelatedProvider;
import com.intellij.navigation.NavigationItem;
+import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
+import com.intellij.openapi.ui.popup.PopupStep;
+import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
+import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.ElementBase;
import com.intellij.psi.search.PsiElementProcessor;
-import com.intellij.ui.JBListWithHintProvider;
+import com.intellij.ui.*;
+import com.intellij.ui.popup.list.ListPopupImpl;
+import com.intellij.ui.popup.list.PopupListElementRenderer;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.util.*;
+import java.util.List;
/**
* @author ven
@@ -220,4 +236,242 @@ public final class NavigationUtil {
}
return attributes;
}
+
+ @NotNull
+ public static JBPopup getRelatedItemsPopup(final List<? extends GotoRelatedItem> items, String title) {
+ Object[] elements = new Object[items.size()];
+ //todo[nik] move presentation logic to GotoRelatedItem class
+ final Map<PsiElement, GotoRelatedItem> itemsMap = new HashMap<PsiElement, GotoRelatedItem>();
+ for (int i = 0; i < items.size(); i++) {
+ GotoRelatedItem item = items.get(i);
+ elements[i] = item.getElement() != null ? item.getElement() : item;
+ itemsMap.put(item.getElement(), item);
+ }
+
+ return getPsiElementPopup(elements, itemsMap, title, new Processor<Object>() {
+ @Override
+ public boolean process(Object element) {
+ if (element instanceof PsiElement) {
+ //noinspection SuspiciousMethodCalls
+ itemsMap.get(element).navigate();
+ }
+ else {
+ ((GotoRelatedItem)element).navigate();
+ }
+ return true;
+ }
+ }
+ );
+ }
+
+ private static JBPopup getPsiElementPopup(final Object[] elements, final Map<PsiElement, GotoRelatedItem> itemsMap,
+ final String title, final Processor<Object> processor) {
+
+ final Ref<Boolean> hasMnemonic = Ref.create(false);
+ final DefaultPsiElementCellRenderer renderer = new DefaultPsiElementCellRenderer() {
+ {
+ setFocusBorderEnabled(false);
+ }
+
+ @Override
+ public String getElementText(PsiElement element) {
+ String customName = itemsMap.get(element).getCustomName();
+ return (customName != null ? customName : super.getElementText(element));
+ }
+
+ @Override
+ protected Icon getIcon(PsiElement element) {
+ Icon customIcon = itemsMap.get(element).getCustomIcon();
+ return customIcon != null ? customIcon : super.getIcon(element);
+ }
+
+ @Override
+ public String getContainerText(PsiElement element, String name) {
+ String customContainerName = itemsMap.get(element).getCustomContainerName();
+
+ if (customContainerName != null) {
+ return customContainerName;
+ }
+ PsiFile file = element.getContainingFile();
+ return file != null && !getElementText(element).equals(file.getName())
+ ? "(" + file.getName() + ")"
+ : null;
+ }
+
+ @Override
+ protected DefaultListCellRenderer getRightCellRenderer(Object value) {
+ return null;
+ }
+
+ @Override
+ protected boolean customizeNonPsiElementLeftRenderer(ColoredListCellRenderer renderer,
+ JList list,
+ Object value,
+ int index,
+ boolean selected,
+ boolean hasFocus) {
+ final GotoRelatedItem item = (GotoRelatedItem)value;
+ Color color = list.getForeground();
+ final SimpleTextAttributes nameAttributes = new SimpleTextAttributes(Font.PLAIN, color);
+ final String name = item.getCustomName();
+ if (name == null) return false;
+ renderer.append(name, nameAttributes);
+ renderer.setIcon(item.getCustomIcon());
+ return true;
+ }
+
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ final JPanel component = (JPanel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+ if (!hasMnemonic.get()) return component;
+
+ final JPanel panelWithMnemonic = new JPanel(new BorderLayout());
+ final int mnemonic = getMnemonic(value, itemsMap);
+ final JLabel label = new JLabel("");
+ if (mnemonic != -1) {
+ label.setText(mnemonic + ".");
+ label.setDisplayedMnemonicIndex(0);
+ }
+ label.setPreferredSize(new JLabel("8.").getPreferredSize());
+
+ final JComponent leftRenderer = (JComponent)component.getComponents()[0];
+ component.remove(leftRenderer);
+ panelWithMnemonic.setBorder(BorderFactory.createEmptyBorder(0, 7, 0, 0));
+ panelWithMnemonic.setBackground(leftRenderer.getBackground());
+ label.setBackground(leftRenderer.getBackground());
+ panelWithMnemonic.add(label, BorderLayout.WEST);
+ panelWithMnemonic.add(leftRenderer, BorderLayout.CENTER);
+ component.add(panelWithMnemonic);
+ return component;
+ }
+ };
+ final ListPopupImpl popup = new ListPopupImpl(new BaseListPopupStep<Object>(title, Arrays.asList(elements)) {
+ @Override
+ public boolean isSpeedSearchEnabled() {
+ return true;
+ }
+
+ @Override
+ public String getIndexedString(Object value) {
+ if (value instanceof GotoRelatedItem) {
+ //noinspection ConstantConditions
+ return ((GotoRelatedItem)value).getCustomName();
+ }
+ final PsiElement element = (PsiElement)value;
+ return renderer.getElementText(element) + " " + renderer.getContainerText(element, null);
+ }
+
+ @Override
+ public PopupStep onChosen(Object selectedValue, boolean finalChoice) {
+ processor.process(selectedValue);
+ return super.onChosen(selectedValue, finalChoice);
+ }
+ }) {
+ };
+ popup.getList().setCellRenderer(new PopupListElementRenderer(popup) {
+ Map<Object, String> separators = new HashMap<Object, String>();
+ {
+ final ListModel model = popup.getList().getModel();
+ String current = null;
+ boolean hasTitle = false;
+ for (int i = 0; i < model.getSize(); i++) {
+ final Object element = model.getElementAt(i);
+ final GotoRelatedItem item = itemsMap.get(element);
+ if (item != null && !StringUtil.equals(current, item.getGroup())) {
+ current = item.getGroup();
+ separators.put(element, current);
+ if (!hasTitle && !StringUtil.isEmpty(current)) {
+ hasTitle = true;
+ }
+ }
+ }
+
+ if (!hasTitle) {
+ separators.remove(model.getElementAt(0));
+ }
+ }
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ final Component component = renderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
+ final String separator = separators.get(value);
+
+ if (separator != null) {
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(component, BorderLayout.CENTER);
+ final SeparatorWithText sep = new SeparatorWithText() {
+ @Override
+ protected void paintComponent(Graphics g) {
+ g.setColor(new JBColor(Color.WHITE, UIUtil.getSeparatorColor()));
+ g.fillRect(0,0,getWidth(), getHeight());
+ super.paintComponent(g);
+ }
+ };
+ sep.setCaption(separator);
+ panel.add(sep, BorderLayout.NORTH);
+ return panel;
+ }
+ return component;
+ }
+ });
+
+ popup.setMinimumSize(new Dimension(200, -1));
+
+ for (Object item : elements) {
+ final int mnemonic = getMnemonic(item, itemsMap);
+ if (mnemonic != -1) {
+ final Action action = createNumberAction(mnemonic, popup, itemsMap, processor);
+ popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke(String.valueOf(mnemonic)), action);
+ popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke("NUMPAD" + String.valueOf(mnemonic)), action);
+ hasMnemonic.set(true);
+ }
+ }
+ return popup;
+ }
+
+ private static Action createNumberAction(final int mnemonic,
+ final ListPopupImpl listPopup,
+ final Map<PsiElement, GotoRelatedItem> itemsMap,
+ final Processor<Object> processor) {
+ return new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ for (final Object item : listPopup.getListStep().getValues()) {
+ if (getMnemonic(item, itemsMap) == mnemonic) {
+ listPopup.setFinalRunnable(new Runnable() {
+ @Override
+ public void run() {
+ processor.process(item);
+ }
+ });
+ listPopup.closeOk(null);
+ }
+ }
+ }
+ };
+ }
+
+ private static int getMnemonic(Object item, Map<PsiElement, GotoRelatedItem> itemsMap) {
+ return (item instanceof GotoRelatedItem ? (GotoRelatedItem)item : itemsMap.get((PsiElement)item)).getMnemonic();
+ }
+
+ @NotNull
+ public static List<GotoRelatedItem> collectRelatedItems(@NotNull PsiElement contextElement, @Nullable DataContext dataContext) {
+ Set<GotoRelatedItem> items = ContainerUtil.newLinkedHashSet();
+ for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) {
+ items.addAll(provider.getItems(contextElement));
+ if (dataContext != null) {
+ items.addAll(provider.getItems(dataContext));
+ }
+ }
+ GotoRelatedItem[] result = items.toArray(new GotoRelatedItem[items.size()]);
+ Arrays.sort(result, new Comparator<GotoRelatedItem>() {
+ @Override
+ public int compare(GotoRelatedItem i1, GotoRelatedItem i2) {
+ String o1 = i1.getGroup();
+ String o2 = i2.getGroup();
+ return StringUtil.isEmpty(o1) ? 1 : StringUtil.isEmpty(o2) ? -1 : o1.compareTo(o2);
+ }
+ });
+ return Arrays.asList(result);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java b/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java
index eeb5e04b8aab..4ea365f34b0c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/problems/MockWolfTheProblemSolver.java
@@ -44,6 +44,11 @@ public class MockWolfTheProblemSolver extends WolfTheProblemSolver {
}
@Override
+ public void weHaveGotNonIgnorableProblems(@NotNull VirtualFile virtualFile, @NotNull List<Problem> problems) {
+ if (myDelegate != null) myDelegate.weHaveGotNonIgnorableProblems(virtualFile, problems);
+ }
+
+ @Override
public boolean hasProblemFilesBeneath(@NotNull final Condition<VirtualFile> condition) {
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java
index 45b4532713c4..fab185e6ddc0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/problems/WolfTheProblemSolverImpl.java
@@ -413,6 +413,12 @@ public class WolfTheProblemSolverImpl extends WolfTheProblemSolver {
public void weHaveGotProblems(@NotNull final VirtualFile virtualFile, @NotNull List<Problem> problems) {
if (problems.isEmpty()) return;
if (!isToBeHighlighted(virtualFile)) return;
+ weHaveGotNonIgnorableProblems(virtualFile, problems);
+ }
+
+ @Override
+ public void weHaveGotNonIgnorableProblems(@NotNull VirtualFile virtualFile, @NotNull List<Problem> problems) {
+ if (problems.isEmpty()) return;
boolean fireListener = false;
synchronized (myProblems) {
ProblemFileInfo storedProblems = myProblems.get(virtualFile);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
index 516ed9118c8c..0c838cd05ec5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java
@@ -212,8 +212,11 @@ public class TemplateState implements Disposable {
if (variableName.equals(TemplateImpl.END)) {
return new TextResult("");
}
- if (myPredefinedVariableValues != null && myPredefinedVariableValues.containsKey(variableName)) {
- return new TextResult(myPredefinedVariableValues.get(variableName));
+ if (myPredefinedVariableValues != null) {
+ String text = myPredefinedVariableValues.get(variableName);
+ if (text != null) {
+ return new TextResult(text);
+ }
}
CharSequence text = myDocument.getCharsSequence();
int segmentNumber = myTemplate.getVariableSegmentNumber(variableName);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java
index f6b0cedae31e..2989f0d0c97c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ChooserExpressionSelector.java
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.template.postfix.templates;
+
import com.intellij.codeInsight.unwrap.ScopeHighlighter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
@@ -30,45 +31,43 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
- * @author ignatov
+ * See {@link PostfixTemplateExpressionSelector} for description
*/
-public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTemplate {
+public class ChooserExpressionSelector implements PostfixTemplateExpressionSelector {
@NotNull
- protected final PostfixTemplatePsiInfoBase myInfo;
+ private final Condition<PsiElement> myCondition;
- protected ExpressionPostfixTemplateWithChooser(@NotNull String name, @NotNull String example, @NotNull PostfixTemplatePsiInfoBase info) {
- super(name, example);
- myInfo = info;
+ public ChooserExpressionSelector(@NotNull Condition<PsiElement> condition) {
+ myCondition = condition;
}
- protected ExpressionPostfixTemplateWithChooser(@NotNull String name,
- @NotNull String key,
- @NotNull String example,
- @NotNull PostfixTemplatePsiInfoBase info) {
- super(name, key, example);
- myInfo = info;
- }
- @Override
- public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
- return !getExpressions(context, copyDocument, newOffset).isEmpty();
+ public boolean hasExpression(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+ @NotNull PsiElement context,
+ @NotNull Document copyDocument,
+ int newOffset) {
+ return !getExpressions(postfixTemplate, context, copyDocument, newOffset).isEmpty();
}
- @Override
- public void expand(@NotNull PsiElement context, @NotNull final Editor editor) {
- List<PsiElement> expressions = getExpressions(context, editor.getDocument(), editor.getCaretModel().getOffset());
+ public void expandTemplate(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+ @NotNull PsiElement context,
+ @NotNull final Editor editor) {
+ List<PsiElement> expressions =
+ getExpressions(postfixTemplate, context, editor.getDocument(), editor.getCaretModel().getOffset());
if (expressions.isEmpty()) {
PostfixTemplatesUtils.showErrorHint(context.getProject(), editor);
}
else if (expressions.size() == 1) {
- doIt(editor, expressions.get(0));
+ postfixTemplate.expandForChooseExpression(expressions.get(0), editor);
}
else {
if (ApplicationManager.getApplication().isUnitTestMode()) {
- doIt(editor, expressions.get(expressions.size() - 1));
+ PsiElement item = ContainerUtil.getLastItem(expressions);
+ assert item != null;
+ postfixTemplate.expandForChooseExpression(item, editor);
return;
}
@@ -81,22 +80,25 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla
public void run() {
CommandProcessor.getInstance().executeCommand(e.getProject(), new Runnable() {
public void run() {
- doIt(editor, e);
+ postfixTemplate.expandForChooseExpression(e, editor);
}
}, "Expand postfix template", PostfixLiveTemplate.POSTFIX_TEMPLATE_ID);
}
});
}
},
- myInfo.getRenderer(),
+ postfixTemplate.getPsiInfo().getRenderer(),
"Expressions", 0, ScopeHighlighter.NATURAL_RANGER
);
}
}
@NotNull
- protected List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, final int offset) {
- List<PsiElement> possibleExpressions = myInfo.getExpressions(context, document, offset);
+ private List<PsiElement> getExpressions(@NotNull PostfixTemplateWithExpressionSelector postfixTemplate,
+ @NotNull PsiElement context,
+ @NotNull Document document,
+ final int offset) {
+ List<PsiElement> possibleExpressions = postfixTemplate.getPsiInfo().getExpressions(context, document, offset);
List<PsiElement> expressions = ContainerUtil.filter(possibleExpressions,
new Condition<PsiElement>() {
@Override
@@ -105,19 +107,13 @@ public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTempla
}
}
);
- return ContainerUtil.filter(expressions.isEmpty() ? maybeTopmostExpression(context) : expressions, getTypeCondition());
+ return ContainerUtil
+ .filter(expressions.isEmpty() ? maybeTopmostExpression(postfixTemplate, context) : expressions, myCondition);
}
- @NotNull
- @SuppressWarnings("unchecked")
- protected Condition<PsiElement> getTypeCondition() {
- return Condition.TRUE;
- }
@NotNull
- private List<PsiElement> maybeTopmostExpression(@NotNull PsiElement context) {
- return ContainerUtil.createMaybeSingletonList(myInfo.getTopmostExpression(context));
+ private static List<PsiElement> maybeTopmostExpression(@NotNull PostfixTemplateWithExpressionSelector postfixTemplate, @NotNull PsiElement context) {
+ return ContainerUtil.createMaybeSingletonList(postfixTemplate.getPsiInfo().getTopmostExpression(context));
}
-
- protected abstract void doIt(@NotNull Editor editor, @NotNull PsiElement expression);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java
index 9c1d9c66b94d..3944cd930af0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/NotPostfixTemplate.java
@@ -16,26 +16,34 @@
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
-public class NotPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
- public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfoBase info) {
- super("not", "!expr", info);
+public class NotPostfixTemplate extends PostfixTemplateWithExpressionSelector {
+
+ public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfo info, @NotNull Condition<PsiElement> typeChecker) {
+ super("not", "!expr", info, selectorWithChooser(typeChecker));
}
+ public NotPostfixTemplate(@NotNull PostfixTemplatePsiInfo info) {
+ super("not", "!expr", info, selectorWithChooser());
+ }
public NotPostfixTemplate(@NotNull String name,
@NotNull String key,
@NotNull String example,
- @NotNull PostfixTemplatePsiInfoBase info) {
- super(name, key, example, info);
+ @NotNull PostfixTemplatePsiInfo info,
+ @NotNull Condition<PsiElement> typeChecker
+ ) {
+ super(name, key, example, info, selectorWithChooser(typeChecker));
}
@Override
- protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) {
- PsiElement element = myInfo.getNegatedExpression(expression);
+ protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
+ PsiElement element = myPsiInfo.getNegatedExpression(expression);
expression.replace(element);
}
} \ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java
index 9a5d03a9359c..3f1dd1143348 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedPostfixTemplate.java
@@ -16,16 +16,25 @@
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
-public class ParenthesizedPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
- public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfoBase psiInfo) {
- super("par", "(expr)", psiInfo);
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorWithChooser;
+
+public class ParenthesizedPostfixTemplate extends PostfixTemplateWithExpressionSelector {
+
+ public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfo psiInfo, Condition<PsiElement> condition) {
+ super("par", "(expr)", psiInfo, selectorWithChooser(condition));
+ }
+
+
+ public ParenthesizedPostfixTemplate(PostfixTemplatePsiInfo psiInfo) {
+ super("par", "(expr)", psiInfo, selectorWithChooser());
}
@Override
- protected void doIt(@NotNull Editor editor, @NotNull PsiElement expression) {
- expression.replace(myInfo.createExpression(expression, "(", ")"));
+ protected void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor) {
+ expression.replace(myPsiInfo.createExpression(expression, "(", ")"));
}
} \ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.java
new file mode 100644
index 000000000000..6b5d559da1de
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateExpressionSelector.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.codeInsight.template.postfix.templates;
+
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Interface provides method used in {@link com.intellij.codeInsight.template.postfix.templates.PostfixTemplateWithExpressionSelector}
+ *
+ * You should implement the interface if you have non-trivial logic how to determine expression for next processing in postfix template
+ * Otherwise, you can use one of existing simple implementations:
+ *
+ * 1) {@link com.intellij.codeInsight.template.postfix.templates.ChooserExpressionSelector} - The selector get all expression
+ * in the current position and show to user chooser for these expressions.
+ *
+ * 2) {@link com.intellij.codeInsight.template.postfix.templates.TopmostExpressionSelector} - The selector pass to postfix template
+ * top most expression in the current position
+ *
+ *
+ */
+public interface PostfixTemplateExpressionSelector {
+
+ /**
+ * Check that we can select not-null expression(PsiElement) in current context
+ */
+ boolean hasExpression(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+ @NotNull PsiElement context,
+ @NotNull Document copyDocument,
+ int newOffset);
+
+ /**
+ * Select expression(PsiElement) and call postfixTemplate.expandForChooseExpression for selected expression
+ */
+ void expandTemplate(@NotNull final PostfixTemplateWithExpressionSelector postfixTemplate,
+ @NotNull PsiElement context,
+ @NotNull final Editor editor);
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java
index 8f4716787453..6664d6404d64 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfo.java
@@ -16,25 +16,42 @@
package com.intellij.codeInsight.template.postfix.templates;
+import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiElement;
+import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public interface PostfixTemplatePsiInfo {
+import java.util.List;
+
+public abstract class PostfixTemplatePsiInfo {
@NotNull
- PsiElement createStatement(@NotNull PsiElement context,
- @NotNull String prefix,
- @NotNull String suffix);
+ public abstract PsiElement createStatement(@NotNull PsiElement context,
+ @NotNull String prefix,
+ @NotNull String suffix);
@NotNull
- PsiElement createExpression(@NotNull PsiElement context,
- @NotNull String prefix,
- @NotNull String suffix);
+ public abstract PsiElement createExpression(@NotNull PsiElement context,
+ @NotNull String prefix,
+ @NotNull String suffix);
@Nullable
- PsiElement getTopmostExpression(@NotNull PsiElement element);
+ public abstract PsiElement getTopmostExpression(@NotNull PsiElement element);
+
+ @NotNull
+ public abstract PsiElement getNegatedExpression(@NotNull PsiElement element);
+
+ @NotNull
+ public abstract List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, int offset);
@NotNull
- PsiElement getNegatedExpression(@NotNull PsiElement element);
+ public Function<PsiElement, String> getRenderer() {
+ return new Function<PsiElement, String>() {
+ @Override
+ public String fun(@NotNull PsiElement element) {
+ return element.getText();
+ }
+ };
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java
deleted file mode 100644
index 7254e651ce41..000000000000
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatePsiInfoBase.java
+++ /dev/null
@@ -1,39 +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 com.intellij.codeInsight.template.postfix.templates;
-
-import com.intellij.openapi.editor.Document;
-import com.intellij.psi.PsiElement;
-import com.intellij.util.Function;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.List;
-
-public abstract class PostfixTemplatePsiInfoBase implements PostfixTemplatePsiInfo {
-
- @NotNull
- public abstract List<PsiElement> getExpressions(@NotNull PsiElement context, @NotNull Document document, int newOffset);
-
- @NotNull
- public Function<PsiElement, String> getRenderer() {
- return new Function<PsiElement, String>() {
- @Override
- public String fun(@NotNull PsiElement element) {
- return element.getText();
- }
- };
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java
new file mode 100644
index 000000000000..d7cfbafdf7a8
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateWithExpressionSelector.java
@@ -0,0 +1,83 @@
+/*
+ * 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.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorTopmost;
+
+public abstract class PostfixTemplateWithExpressionSelector extends PostfixTemplate {
+
+ @NotNull
+ protected final PostfixTemplatePsiInfo myPsiInfo;
+ @NotNull
+ private final PostfixTemplateExpressionSelector mySelector;
+
+ protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+ @NotNull String key,
+ @NotNull String example,
+ @NotNull PostfixTemplatePsiInfo psiInfo,
+ @NotNull PostfixTemplateExpressionSelector selector) {
+ super(name, key, example);
+ myPsiInfo = psiInfo;
+ mySelector = selector;
+ }
+
+
+ protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+ @NotNull String example,
+ @NotNull PostfixTemplatePsiInfo psiInfo,
+ @NotNull PostfixTemplateExpressionSelector selector) {
+ super(name, example);
+ myPsiInfo = psiInfo;
+ mySelector = selector;
+ }
+
+ protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+ @NotNull String example,
+ @NotNull PostfixTemplatePsiInfo psiInfo,
+ @NotNull Condition<PsiElement> typeChecker) {
+ this(name, example, psiInfo, selectorTopmost(typeChecker));
+ }
+
+ protected PostfixTemplateWithExpressionSelector(@NotNull String name,
+ @NotNull String example,
+ @NotNull PostfixTemplatePsiInfo psiInfo) {
+ this(name, example, psiInfo, selectorTopmost());
+ }
+
+
+ @Override
+ public final boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ return mySelector.hasExpression(this, context, copyDocument, newOffset);
+ }
+
+ @Override
+ public final void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ mySelector.expandTemplate(this, context, editor);
+ }
+
+ protected abstract void expandForChooseExpression(@NotNull PsiElement expression, @NotNull Editor editor);
+
+ @NotNull
+ PostfixTemplatePsiInfo getPsiInfo() {
+ return myPsiInfo;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
index 877e10b53490..5ff744e3d72a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplatesUtils.java
@@ -21,6 +21,8 @@ import com.intellij.lang.surroundWith.Surrounder;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.util.CommonRefactoringUtil;
@@ -31,6 +33,22 @@ public abstract class PostfixTemplatesUtils {
private PostfixTemplatesUtils() {
}
+ public static PostfixTemplateExpressionSelector selectorWithChooser() {
+ return selectorWithChooser(Conditions.<PsiElement>alwaysTrue());
+ }
+
+ public static PostfixTemplateExpressionSelector selectorTopmost() {
+ return selectorTopmost(Conditions.<PsiElement>alwaysTrue());
+ }
+
+ public static PostfixTemplateExpressionSelector selectorWithChooser(Condition<PsiElement> condition) {
+ return new ChooserExpressionSelector(condition);
+ }
+
+ public static PostfixTemplateExpressionSelector selectorTopmost(Condition<PsiElement> condition) {
+ return new TopmostExpressionSelector(condition);
+ }
+
@Nullable
public static TextRange surround(@NotNull Surrounder surrounder,
@NotNull Editor editor,
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java
index ed1605d3a9fb..5b5c3624f33b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementWrapPostfixTemplate.java
@@ -22,7 +22,7 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
-public abstract class StatementWrapPostfixTemplate extends TypedPostfixTemplate {
+public abstract class StatementWrapPostfixTemplate extends PostfixTemplateWithExpressionSelector {
@SuppressWarnings("unchecked")
protected StatementWrapPostfixTemplate(@NotNull String name,
@@ -39,9 +39,7 @@ public abstract class StatementWrapPostfixTemplate extends TypedPostfixTemplate
}
@Override
- public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
- PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context);
- assert topmostExpression != null;
+ public void expandForChooseExpression(@NotNull PsiElement topmostExpression, @NotNull Editor editor) {
PsiElement parent = topmostExpression.getParent();
PsiElement expression = getWrappedExpression(topmostExpression);
PsiElement replace = parent.replace(expression);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java
index 4d6582f071de..9f19b2011a49 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/StringBasedPostfixTemplate.java
@@ -26,7 +26,7 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public abstract class StringBasedPostfixTemplate extends TypedPostfixTemplate {
+public abstract class StringBasedPostfixTemplate extends PostfixTemplateWithExpressionSelector {
public StringBasedPostfixTemplate(@NotNull String name,
@NotNull String example,
@@ -36,10 +36,8 @@ public abstract class StringBasedPostfixTemplate extends TypedPostfixTemplate {
}
@Override
- public final void expand(@NotNull PsiElement context, @NotNull Editor editor) {
- PsiElement expr = myPsiInfo.getTopmostExpression(context);
- assert expr != null;
- Project project = context.getProject();
+ public final void expandForChooseExpression(@NotNull PsiElement expr, @NotNull Editor editor) {
+ Project project = expr.getProject();
Document document = editor.getDocument();
PsiElement elementForRemoving = shouldRemoveParent() ? expr.getParent() : expr;
document.deleteString(elementForRemoving.getTextRange().getStartOffset(), elementForRemoving.getTextRange().getEndOffset());
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
index 52ad0c4cdde8..29ea4d39ac64 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/SurroundPostfixTemplateBase.java
@@ -40,11 +40,9 @@ public abstract class SurroundPostfixTemplateBase extends StatementWrapPostfixTe
@Override
- public void expand(@NotNull PsiElement context, @NotNull final Editor editor) {
+ public final void expandForChooseExpression(@NotNull PsiElement context, @NotNull final Editor editor) {
PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context);
- PsiElement expression = getWrappedExpression(topmostExpression);
- assert topmostExpression != null;
- PsiElement replace = topmostExpression.replace(expression);
+ PsiElement replace = getReplacedExpression(topmostExpression);
TextRange range = PostfixTemplatesUtils.surround(getSurrounder(), editor, replace);
if (range != null) {
@@ -52,6 +50,12 @@ public abstract class SurroundPostfixTemplateBase extends StatementWrapPostfixTe
}
}
+ protected PsiElement getReplacedExpression(PsiElement topmostExpression) {
+ PsiElement expression = getWrappedExpression(topmostExpression);
+ assert topmostExpression != null;
+ return topmostExpression.replace(expression);
+ }
+
public boolean isStatement() {
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java
new file mode 100644
index 000000000000..bd6028d2d8d2
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TopmostExpressionSelector.java
@@ -0,0 +1,58 @@
+/*
+ * 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.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+
+/**
+ * See {@link PostfixTemplateExpressionSelector} for description
+ */
+public class TopmostExpressionSelector implements PostfixTemplateExpressionSelector {
+
+ @NotNull
+ private final Condition<PsiElement> myCondition;
+
+ public TopmostExpressionSelector(@NotNull Condition<PsiElement> condition) {
+
+ myCondition = condition;
+ }
+
+ @Override
+ public boolean hasExpression(@NotNull PostfixTemplateWithExpressionSelector template,
+ @NotNull PsiElement context,
+ @NotNull Document copyDocument,
+ int newOffset) {
+ PsiElement topmostExpression = template.getPsiInfo().getTopmostExpression(context);
+ return topmostExpression != null && myCondition.value(topmostExpression);
+ }
+
+ @Override
+ public void expandTemplate(@NotNull PostfixTemplateWithExpressionSelector template,
+ @NotNull PsiElement context,
+ @NotNull Editor editor) {
+ PostfixTemplatePsiInfo info = template.getPsiInfo();
+ PsiElement expression = info.getTopmostExpression(context);
+ if (expression == null) {
+ return;
+ }
+ template.expandForChooseExpression(expression, editor);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java
deleted file mode 100644
index 0d7d424d99a8..000000000000
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/postfix/templates/TypedPostfixTemplate.java
+++ /dev/null
@@ -1,42 +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 com.intellij.codeInsight.template.postfix.templates;
-
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class TypedPostfixTemplate extends PostfixTemplate {
-
- protected final PostfixTemplatePsiInfo myPsiInfo;
- protected final Condition<PsiElement> myTypeChecker;
-
- protected TypedPostfixTemplate(@NotNull String name,
- @NotNull String example,
- @NotNull PostfixTemplatePsiInfo psiInfo,
- @NotNull Condition<PsiElement> typeChecker) {
- super(name, example);
- this.myPsiInfo = psiInfo;
- this.myTypeChecker = typeChecker;
- }
-
- @Override
- public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
- PsiElement topmostExpression = myPsiInfo.getTopmostExpression(context);
- return topmostExpression != null && myTypeChecker.value(topmostExpression);
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java
index 2c934d76bbd5..7ae94888c90d 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionManagerEx.java
@@ -64,6 +64,8 @@ public class InspectionManagerEx extends InspectionManagerBase {
@NotNull
@Override
protected ContentManager compute() {
+ ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
+ toolWindowManager.registerToolWindow(ToolWindowId.INSPECTION, true, ToolWindowAnchor.BOTTOM, project);
return ContentFactory.SERVICE.getInstance().createContentManager(new TabbedPaneContentUI(), true, project);
}
};
diff --git a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
index f19d92f76bcf..b27a939dd57c 100644
--- a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
+++ b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
@@ -74,7 +74,7 @@ public class ProgramRunnerUtil {
}
public static void executeConfiguration(Project project,
- DataContext context,
+ @Nullable DataContext context,
@Nullable RunnerAndConfigurationSettings configuration,
Executor executor,
ExecutionTarget target,
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
index 6c0bfffd450e..9aab415d5e70 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
@@ -45,7 +45,9 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.util.ExceptionUtil;
import com.intellij.util.ObjectUtils;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.SafeFileOutputStream;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.xml.XppReader;
@@ -56,7 +58,6 @@ import org.xmlpull.v1.XmlSerializer;
import java.awt.event.KeyEvent;
import java.io.*;
-import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
@@ -65,6 +66,8 @@ import java.util.ListIterator;
*/
public class ConsoleHistoryController {
+ private static final int VERSION = 1;
+
private static final Logger LOG = Logger.getInstance("com.intellij.execution.console.ConsoleHistoryController");
private final LanguageConsoleImpl myConsole;
@@ -394,7 +397,15 @@ public class ConsoleHistoryController {
}
}
catch (Exception ex) {
- LOG.error(ex);
+ //noinspection ThrowableResultOfMethodCallIgnored
+ Throwable cause = ExceptionUtil.getRootCause(ex);
+ if (cause instanceof EOFException) {
+ LOG.warn("Failed to load " + myType + " console history from: " + file.getPath(), ex);
+ return false;
+ }
+ else {
+ LOG.error(ex);
+ }
}
finally {
if (xmlReader != null) {
@@ -423,6 +434,7 @@ public class ConsoleHistoryController {
}
serializer.setOutput(os = new SafeFileOutputStream(file), CharsetToolkit.UTF8);
saveHistory(serializer);
+ serializer.flush();
}
catch (Exception ex) {
LOG.error(ex);
@@ -439,47 +451,58 @@ public class ConsoleHistoryController {
}
@Nullable
- private String loadHistory(final HierarchicalStreamReader in, final String expectedId) {
+ private String loadHistory(HierarchicalStreamReader in, String expectedId) {
if (!in.getNodeName().equals("console-history")) return null;
- final String id = in.getAttribute("id");
+ int version = StringUtil.parseInt(in.getAttribute("version"), 0);
+ String id = in.getAttribute("id");
if (!expectedId.equals(id)) return null;
- final ArrayList<String> entries = new ArrayList<String>();
+ List<String> entries = ContainerUtil.newArrayList();
String consoleContent = null;
while (in.hasMoreChildren()) {
in.moveDown();
if ("history-entry".equals(in.getNodeName())) {
- entries.add(in.getValue());
+ entries.add(StringUtil.notNullize(in.getValue()));
}
else if ("console-content".equals(in.getNodeName())) {
- consoleContent = in.getValue();
+ consoleContent = StringUtil.notNullize(in.getValue());
}
in.moveUp();
}
for (ListIterator<String> iterator = entries.listIterator(entries.size()); iterator.hasPrevious(); ) {
- final String entry = iterator.previous();
+ String entry = iterator.previous();
getModel().addToHistory(entry);
}
return consoleContent;
}
- private void saveHistory(final XmlSerializer out) throws IOException {
+ private void saveHistory(XmlSerializer out) throws IOException {
out.startDocument(CharsetToolkit.UTF8, null);
out.startTag(null, "console-history");
+ out.attribute(null, "version", String.valueOf(VERSION));
out.attribute(null, "id", myId);
- for (String s : getModel().getHistory()) {
- out.startTag(null, "history-entry");
- out.text(s);
- out.endTag(null, "history-entry");
+ try {
+ for (String s : getModel().getHistory()) {
+ textTag(out, "history-entry", s);
+ }
+ String current = myContent;
+ if (StringUtil.isNotEmpty(current)) {
+ textTag(out, "console-content", current);
+ }
}
- String current = myContent;
- if (StringUtil.isNotEmpty(current)) {
- out.startTag(null, "console-content");
- out.text(current);
- out.endTag(null, "console-content");
+ finally {
+ out.endTag(null, "console-history");
+ out.endDocument();
}
- out.endTag(null, "console-history");
- out.endDocument();
}
}
+ private static void textTag(@NotNull XmlSerializer out, @NotNull String tag, @NotNull String text) throws IOException {
+ out.startTag(null, tag);
+ try {
+ out.cdsect(text);
+ }
+ finally {
+ out.endTag(null, tag);
+ }
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java b/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java
index c760310cd391..87e1323fe607 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/DuplexConsoleView.java
@@ -9,6 +9,7 @@ import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.ui.ObservableConsoleView;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -34,6 +35,8 @@ public class DuplexConsoleView<S extends ConsoleView, T extends ConsoleView> ext
private final S myPrimaryConsoleView;
@NotNull
private final T mySecondaryConsoleView;
+ @Nullable
+ private final String myStateStorageKey;
private boolean myPrimary;
@Nullable
@@ -41,25 +44,46 @@ public class DuplexConsoleView<S extends ConsoleView, T extends ConsoleView> ext
@NotNull
private final SwitchDuplexConsoleViewAction mySwitchConsoleAction;
+
public DuplexConsoleView(@NotNull S primaryConsoleView, @NotNull T secondaryConsoleView) {
+ this(primaryConsoleView, secondaryConsoleView, null);
+ }
+
+ public DuplexConsoleView(@NotNull S primaryConsoleView, @NotNull T secondaryConsoleView, @Nullable String stateStorageKey) {
super(new CardLayout());
myPrimaryConsoleView = primaryConsoleView;
mySecondaryConsoleView = secondaryConsoleView;
+ myStateStorageKey = stateStorageKey;
add(myPrimaryConsoleView.getComponent(), PRIMARY_CONSOLE_PANEL);
add(mySecondaryConsoleView.getComponent(), SECONDARY_CONSOLE_PANEL);
- mySwitchConsoleAction = new SwitchDuplexConsoleViewAction(this);
+ mySwitchConsoleAction = new SwitchDuplexConsoleViewAction();
myPrimary = true;
- enableConsole(false);
+ enableConsole(getStoredState());
Disposer.register(this, myPrimaryConsoleView);
Disposer.register(this, mySecondaryConsoleView);
}
- public static <S extends ConsoleView, T extends ConsoleView> DuplexConsoleView<S, T> create(S primary, T secondary) {
- return new DuplexConsoleView<S, T>(primary, secondary);
+ public static <S extends ConsoleView, T extends ConsoleView> DuplexConsoleView<S, T> create(@NotNull S primary,
+ @NotNull T secondary,
+ @Nullable String stateStorageKey) {
+ return new DuplexConsoleView<S, T>(primary, secondary, stateStorageKey);
+ }
+
+ private void setStoredState(boolean primary) {
+ if (myStateStorageKey != null) {
+ PropertiesComponent.getInstance().setValue(myStateStorageKey, String.valueOf(primary));
+ }
+ }
+
+ private boolean getStoredState() {
+ if (myStateStorageKey == null) {
+ return false;
+ }
+ return PropertiesComponent.getInstance().getBoolean(myStateStorageKey, false);
}
public void enableConsole(boolean primary) {
@@ -215,23 +239,22 @@ public class DuplexConsoleView<S extends ConsoleView, T extends ConsoleView> ext
return mySwitchConsoleAction.getTemplatePresentation();
}
- private static class SwitchDuplexConsoleViewAction extends ToggleAction implements DumbAware {
- private final DuplexConsoleView myConsole;
+ private class SwitchDuplexConsoleViewAction extends ToggleAction implements DumbAware {
- public SwitchDuplexConsoleViewAction(final DuplexConsoleView console) {
+ public SwitchDuplexConsoleViewAction() {
super(ExecutionBundle.message("run.configuration.show.command.line.action.name"), null,
AllIcons.Debugger.ToolConsole);
- myConsole = console;
}
@Override
public boolean isSelected(final AnActionEvent event) {
- return !myConsole.isPrimaryConsoleEnabled();
+ return !isPrimaryConsoleEnabled();
}
@Override
public void setSelected(final AnActionEvent event, final boolean flag) {
- myConsole.enableConsole(!flag);
+ enableConsole(!flag);
+ setStoredState(!flag);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
@@ -244,12 +267,12 @@ public class DuplexConsoleView<S extends ConsoleView, T extends ConsoleView> ext
public void update(final AnActionEvent event) {
super.update(event);
final Presentation presentation = event.getPresentation();
- final boolean isRunning = myConsole.myProcessHandler != null && !myConsole.myProcessHandler.isProcessTerminated();
+ final boolean isRunning = myProcessHandler != null && !myProcessHandler.isProcessTerminated();
if (isRunning) {
presentation.setEnabled(true);
}
else {
- myConsole.enableConsole(true);
+ enableConsole(true);
presentation.putClientProperty(SELECTED_PROPERTY, false);
presentation.setEnabled(false);
}
diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
index 9cb57be6ad9d..1a9afd1e25e5 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
@@ -670,12 +670,14 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
}
}
+ @NotNull
public Editor getCurrentEditor() {
- return ObjectUtils.chooseNotNull(myCurrentEditor, myConsoleEditor);
+ return ObjectUtils.notNull(myCurrentEditor, myConsoleEditor);
}
+ @NotNull
public Language getLanguage() {
- return myVirtualFile.getLanguage();
+ return ObjectUtils.assertNotNull(myVirtualFile.getLanguage());
}
public void setLanguage(@NotNull Language language) {
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
index ae6af9d1064e..edf1352a760c 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java
@@ -49,6 +49,8 @@ import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;
@@ -345,6 +347,14 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
mySettings = settings;
init();
myJBList.setSelectedValue(mySelectedSettings, true);
+ myJBList.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() ==2) {
+ doOKAction();
+ }
+ }
+ });
FontMetrics fontMetrics = myJBList.getFontMetrics(myJBList.getFont());
int maxWidth = fontMetrics.stringWidth("m") * 30;
for (RunnerAndConfigurationSettings setting : settings) {
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
index df7f7e1b2e1c..b4b3cd919ec4 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
@@ -15,6 +15,9 @@
*/
package com.intellij.execution.runners;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionHelper;
import com.intellij.execution.ExecutionManager;
@@ -129,38 +132,30 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
registerActionShortcuts(actions, getLanguageConsole().getConsoleEditor().getComponent());
registerActionShortcuts(actions, panel);
panel.updateUI();
+
showConsole(defaultExecutor, contentDescriptor);
// Run
myProcessHandler.startNotify();
}
- private String constructConsoleTitle(final @NotNull String consoleTitle) {
+ protected String constructConsoleTitle(final @NotNull String consoleTitle) {
if (shouldAddNumberToTitle()) {
- List<RunContentDescriptor> consoles = ExecutionHelper.collectConsolesByDisplayName(myProject, new NotNullFunction<String, Boolean>() {
- @NotNull
- @Override
- public Boolean fun(String dom) {
- return dom.contains(consoleTitle);
- }
- });
+ List<String> activeConsoleNames = getActiveConsoleNames(consoleTitle);
int max = 0;
- for (RunContentDescriptor dsc : consoles) {
- ProcessHandler handler = dsc.getProcessHandler();
- if (handler != null && !handler.isProcessTerminated()) {
- if (max == 0) {
- max = 1;
- }
- try {
- int num = Integer.parseInt(dsc.getDisplayName().substring(consoleTitle.length() + 1, dsc.getDisplayName().length() - 1));
- if (num > max) {
- max = num;
- }
- }
- catch (Exception ignored) {
- //skip
+ for (String name : activeConsoleNames) {
+ if (max == 0) {
+ max = 1;
+ }
+ try {
+ int num = Integer.parseInt(name.substring(consoleTitle.length() + 1, name.length() - 1));
+ if (num > max) {
+ max = num;
}
}
+ catch (Exception ignored) {
+ //skip
+ }
}
if (max >= 1) {
return consoleTitle + "(" + (max + 1) + ")";
@@ -178,9 +173,9 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
return false;
}
- protected void showConsole(Executor defaultExecutor, RunContentDescriptor myDescriptor) {
+ protected void showConsole(Executor defaultExecutor, RunContentDescriptor contentDescriptor) {
// Show in run toolwindow
- ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, myDescriptor);
+ ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, contentDescriptor);
}
protected void finishConsole() {
@@ -245,11 +240,13 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
public static AnAction createConsoleExecAction(@NotNull LanguageConsoleView console,
@NotNull ProcessHandler processHandler,
@NotNull ProcessBackedConsoleExecuteActionHandler consoleExecuteActionHandler) {
- return new ConsoleExecuteAction(console, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(), consoleExecuteActionHandler);
+ return new ConsoleExecuteAction(console, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(),
+ consoleExecuteActionHandler);
}
protected AnAction createConsoleExecAction(@NotNull ProcessBackedConsoleExecuteActionHandler consoleExecuteActionHandler) {
- return new ConsoleExecuteAction(myConsoleView, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(), consoleExecuteActionHandler);
+ return new ConsoleExecuteAction(myConsoleView, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(),
+ consoleExecuteActionHandler);
}
@SuppressWarnings("UnusedDeclaration")
@@ -301,4 +298,31 @@ public abstract class AbstractConsoleRunnerWithHistory<T extends LanguageConsole
public ProcessBackedConsoleExecuteActionHandler getConsoleExecuteActionHandler() {
return myConsoleExecuteActionHandler;
}
+
+ protected List<String> getActiveConsoleNames(final String consoleTitle) {
+ return getActiveConsolesFromRunToolWindow(consoleTitle);
+ }
+
+ protected List<String> getActiveConsolesFromRunToolWindow(final String consoleTitle) {
+ List<RunContentDescriptor> consoles = ExecutionHelper.collectConsolesByDisplayName(myProject, new NotNullFunction<String, Boolean>() {
+ @NotNull
+ @Override
+ public Boolean fun(String dom) {
+ return dom.contains(consoleTitle);
+ }
+ });
+
+ return FluentIterable.from(consoles).filter(new Predicate<RunContentDescriptor>() {
+ @Override
+ public boolean apply(RunContentDescriptor input) {
+ ProcessHandler handler = input.getProcessHandler();
+ return handler != null && !handler.isProcessTerminated();
+ }
+ }).transform(new Function<RunContentDescriptor, String>() {
+ @Override
+ public String apply(RunContentDescriptor input) {
+ return input.getDisplayName();
+ }
+ }).toList();
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java b/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java
index 507864126430..20b29c2de994 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RestartAction.java
@@ -61,6 +61,15 @@ public class RestartAction extends FakeRerunAction implements DumbAware, AnActio
myDescriptor = descriptor;
myExecutor = executor;
// see IDEADEV-698
+
+ if (descriptor.getRestarter() == null) {
+ descriptor.setRestarter(new Runnable() {
+ @Override
+ public void run() {
+ restart();
+ }
+ });
+ }
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java b/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java
index ab9433e66831..bb6d206f1eb9 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RunContentBuilder.java
@@ -206,12 +206,6 @@ public class RunContentBuilder extends LogConsoleManagerBase {
final RestartAction restartAction = new RestartAction(myExecutor, myRunner, contentDescriptor, getEnvironment());
restartAction.registerShortcut(component);
actionGroup.add(restartAction);
- contentDescriptor.setRestarter(new Runnable() {
- @Override
- public void run() {
- restartAction.restart();
- }
- });
if (myExecutionResult instanceof DefaultExecutionResult) {
final AnAction[] actions = ((DefaultExecutionResult)myExecutionResult).getRestartActions();
diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
index 897d169e1845..821d9dbd6bc3 100644
--- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
+++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java
@@ -1271,6 +1271,17 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
return null;
}
+ @Nullable
+ public void restoreContent(final String key) {
+ for (AnAction action : myMinimizedViewActions.getChildren(null)) {
+ Content content = ((RestoreViewAction)action).getContent();
+ if (key.equals(content.getUserData(ViewImpl.ID))) {
+ action.actionPerformed(null);
+ return;
+ }
+ }
+ }
+
public void setToDisposeRemovedContent(final boolean toDispose) {
myToDisposeRemovedContent = toDispose;
}
diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
index 8a36638d993c..9613ac0dd33f 100644
--- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
+++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
@@ -392,6 +392,9 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
if (secondaryActionsAvailable()) {
actionGroup.addAction(new ToggleInCommentsAction(this)).setAsSecondary(true);
actionGroup.addAction(new ToggleInLiteralsOnlyAction(this)).setAsSecondary(true);
+ actionGroup.addAction(new ToggleExceptCommentsAction(this)).setAsSecondary(true);
+ actionGroup.addAction(new ToggleExceptLiteralsAction(this)).setAsSecondary(true);
+ actionGroup.addAction(new ToggleExceptCommentsAndLiteralsAction(this)).setAsSecondary(true);
}
actionGroup.addAction(new TogglePreserveCaseAction(this));
actionGroup.addAction(new ToggleSelectionOnlyAction(this));
@@ -473,8 +476,7 @@ public class EditorSearchComponent extends EditorHeaderComponent implements Data
to.setCaseSensitive(from.isCaseSensitive());
to.setWholeWordsOnly(from.isWholeWordsOnly());
to.setRegularExpressions(from.isRegularExpressions());
- to.setInCommentsOnly(from.isInCommentsOnly());
- to.setInStringLiteralsOnly(from.isInStringLiteralsOnly());
+ to.setSearchContext(from.getSearchContext());
if (from.isReplaceState()) {
to.setPreserveCase(from.isPreserveCase());
}
diff --git a/platform/lang-impl/src/com/intellij/find/FindSettings.java b/platform/lang-impl/src/com/intellij/find/FindSettings.java
index 964670a45723..d61fd395eadd 100644
--- a/platform/lang-impl/src/com/intellij/find/FindSettings.java
+++ b/platform/lang-impl/src/com/intellij/find/FindSettings.java
@@ -119,4 +119,13 @@ public abstract class FindSettings{
public abstract boolean isInCommentsOnly();
public abstract void setInCommentsOnly(boolean selected);
+
+ public abstract boolean isExceptStringLiterals();
+ public abstract void setExceptStringLiterals(boolean selected);
+
+ public abstract boolean isExceptComments();
+ public abstract void setExceptComments(boolean selected);
+
+ public abstract boolean isExceptCommentsAndLiterals();
+ public abstract void setExceptCommentsAndLiterals(boolean selected);
}
diff --git a/platform/lang-impl/src/com/intellij/find/FindUtil.java b/platform/lang-impl/src/com/intellij/find/FindUtil.java
index edc906481398..674358a49379 100644
--- a/platform/lang-impl/src/com/intellij/find/FindUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/FindUtil.java
@@ -321,7 +321,7 @@ public class FindUtil {
public static void searchBack(final Project project, final Editor editor, @Nullable DataContext context) {
FindManager findManager = FindManager.getInstance(project);
- if (!findManager.findWasPerformed()) {
+ if (!findManager.findWasPerformed() && !findManager.selectNextOccurrenceWasPerformed()) {
new IncrementalFindAction().getHandler().execute(editor, context);
return;
}
@@ -363,7 +363,7 @@ public class FindUtil {
public static boolean searchAgain(final Project project, final Editor editor, @Nullable DataContext context) {
FindManager findManager = FindManager.getInstance(project);
- if (!findManager.findWasPerformed()) {
+ if (!findManager.findWasPerformed() && !findManager.selectNextOccurrenceWasPerformed()) {
new IncrementalFindAction().getHandler().execute(editor, context);
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java
new file mode 100644
index 000000000000..ae60f31a70b7
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAction.java
@@ -0,0 +1,38 @@
+/*
+ * 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.find.editorHeaderActions;
+
+import com.intellij.find.EditorSearchComponent;
+import com.intellij.find.FindModel;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+public class ToggleExceptCommentsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction {
+ private static final String TEXT = "Except C&omments";
+
+ public ToggleExceptCommentsAction(EditorSearchComponent editorSearchComponent) {
+ super(editorSearchComponent, TEXT);
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return getEditorSearchComponent().getFindModel().isExceptComments();
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_COMMENTS : FindModel.SearchContext.ANY);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java
new file mode 100644
index 000000000000..d3ff1015e610
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptCommentsAndLiteralsAction.java
@@ -0,0 +1,38 @@
+/*
+ * 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.find.editorHeaderActions;
+
+import com.intellij.find.EditorSearchComponent;
+import com.intellij.find.FindModel;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+public class ToggleExceptCommentsAndLiteralsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction {
+ private static final String TEXT = "Except Comments and Li&terals";
+
+ public ToggleExceptCommentsAndLiteralsAction(EditorSearchComponent editorSearchComponent) {
+ super(editorSearchComponent, TEXT);
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return getEditorSearchComponent().getFindModel().isExceptCommentsAndStringLiterals();
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS : FindModel.SearchContext.ANY);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java
new file mode 100644
index 000000000000..4b7f09c2b211
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleExceptLiteralsAction.java
@@ -0,0 +1,38 @@
+/*
+ * 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.find.editorHeaderActions;
+
+import com.intellij.find.EditorSearchComponent;
+import com.intellij.find.FindModel;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+
+public class ToggleExceptLiteralsAction extends EditorHeaderToggleAction implements SecondaryHeaderAction {
+ private static final String TEXT = "Except L&iterals";
+
+ public ToggleExceptLiteralsAction(EditorSearchComponent editorSearchComponent) {
+ super(editorSearchComponent, TEXT);
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return getEditorSearchComponent().getFindModel().isExceptStringLiterals();
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.EXCEPT_STRING_LITERALS : FindModel.SearchContext.ANY);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java
index e6cae36868af..4d9d5ad44cac 100644
--- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInCommentsAction.java
@@ -18,8 +18,6 @@ public class ToggleInCommentsAction extends EditorHeaderToggleAction implements
@Override
public void setSelected(AnActionEvent e, boolean state) {
- FindModel findModel = getEditorSearchComponent().getFindModel();
- findModel.setInCommentsOnly(state);
- if (state) findModel.setInStringLiteralsOnly(false);
+ getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.IN_COMMENTS : FindModel.SearchContext.ANY);
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java
index c4d47e024f5e..d8fc5d530095 100644
--- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleInLiteralsOnlyAction.java
@@ -18,8 +18,6 @@ public class ToggleInLiteralsOnlyAction extends EditorHeaderToggleAction implem
@Override
public void setSelected(AnActionEvent e, boolean state) {
- FindModel findModel = getEditorSearchComponent().getFindModel();
- findModel.setInStringLiteralsOnly(state);
- if (state) findModel.setInCommentsOnly(false);
+ getEditorSearchComponent().getFindModel().setSearchContext(state ? FindModel.SearchContext.IN_STRING_LITERALS : FindModel.SearchContext.ANY);
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
index 7bc0e0c595f8..d7f7665a9299 100644
--- a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
+++ b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
@@ -25,6 +25,7 @@ import com.intellij.find.impl.FindManagerImpl;
import com.intellij.find.replaceInProject.ReplaceInProjectManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
@@ -71,8 +72,14 @@ public class FindInProjectManager {
findModel.setOpenInNewTab(toOpenInNewTab[0]);
FindInProjectUtil.setDirectoryName(findModel, dataContext);
- Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
- FindUtil.initStringToFindWithSelection(findModel, editor);
+ String text = PlatformDataKeys.PREDEFINED_TEXT.getData(dataContext);
+ if (text != null) {
+ FindModel.initStringToFindNoMultiline(findModel, text);
+ }
+ else {
+ Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
+ FindUtil.initStringToFindWithSelection(findModel, editor);
+ }
findManager.showFindDialog(findModel, new Runnable() {
@Override
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java b/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java
index fe47fb8558a6..3315eac0b979 100644
--- a/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/CommonFindUsagesDialog.java
@@ -16,8 +16,8 @@
package com.intellij.find.findUsages;
+import com.intellij.lang.HelpID;
import com.intellij.lang.findUsages.DescriptiveNameUtil;
-import com.intellij.openapi.help.HelpManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
@@ -26,7 +26,9 @@ import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.usageView.UsageViewUtil;
+import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -35,6 +37,7 @@ import javax.swing.*;
*/
public class CommonFindUsagesDialog extends AbstractFindUsagesDialog {
@NotNull protected final PsiElement myPsiElement;
+ @Nullable private final String myHelpId;
public CommonFindUsagesDialog(@NotNull PsiElement element,
@NotNull Project project,
@@ -46,6 +49,7 @@ public class CommonFindUsagesDialog extends AbstractFindUsagesDialog {
super(project, findUsagesOptions, toShowInNewTab, mustOpenInNewTab, isSingleFile, isTextSearch(element, isSingleFile, handler),
!isSingleFile && !element.getManager().isInProject(element));
myPsiElement = element;
+ myHelpId = ObjectUtils.chooseNotNull(handler.getHelpId(), HelpID.FIND_OTHER_USAGES);
init();
}
@@ -71,8 +75,9 @@ public class CommonFindUsagesDialog extends AbstractFindUsagesDialog {
coloredComponent.append(DescriptiveNameUtil.getDescriptiveName(myPsiElement), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
}
+ @Nullable
@Override
- protected void doHelpAction() {
- HelpManager.getInstance().invokeHelp(FindUsagesManager.getHelpID(myPsiElement));
+ protected String getHelpId() {
+ return myHelpId;
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java
index a9291cf612ba..b0dcc459d55b 100644
--- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesHandler.java
@@ -83,6 +83,11 @@ public abstract class FindUsagesHandler {
return PsiElement.EMPTY_ARRAY;
}
+ @Nullable
+ protected String getHelpId() {
+ return FindUsagesManager.getHelpID(myPsiElement);
+ }
+
@NotNull
public static FindUsagesOptions createFindUsagesOptions(@NotNull Project project, @Nullable final DataContext dataContext) {
FindUsagesOptions findUsagesOptions = new FindUsagesOptions(project, dataContext);
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
index b6a6152b678b..c25456da1988 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.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.
@@ -35,7 +35,6 @@ import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.*;
-import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -50,8 +49,6 @@ import com.intellij.ui.EditorComboBoxRenderer;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.StateRestoringCheckBox;
-import com.intellij.ui.components.labels.LinkLabel;
-import com.intellij.ui.components.labels.LinkListener;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
@@ -60,7 +57,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.text.BadLocationException;
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
@@ -78,8 +74,7 @@ public class FindDialog extends DialogWrapper {
private StateRestoringCheckBox myCbCaseSensitive;
private StateRestoringCheckBox myCbPreserveCase;
private StateRestoringCheckBox myCbWholeWordsOnly;
- private StateRestoringCheckBox myCbInCommentsOnly;
- private StateRestoringCheckBox myCbInStringLiteralsOnly;
+ private ComboBox mySearchContext;
private StateRestoringCheckBox myCbRegularExpressions;
private JRadioButton myRbGlobal;
private JRadioButton myRbSelectedText;
@@ -223,7 +218,7 @@ public class FindDialog extends DialogWrapper {
myReplacePrompt.setVisible(myModel.isReplaceState());
myReplaceComboBox.setVisible(myModel.isReplaceState());
if (myCbToSkipResultsWhenOneUsage != null) {
- myCbToSkipResultsWhenOneUsage.setVisible(myModel.isReplaceState());
+ myCbToSkipResultsWhenOneUsage.setVisible(!myModel.isReplaceState());
}
myCbPreserveCase.setVisible(myModel.isReplaceState());
}
@@ -354,9 +349,9 @@ public class FindDialog extends DialogWrapper {
gbConstraints.gridwidth = GridBagConstraints.REMAINDER;
optionsPanel.add(createFilterPanel(),gbConstraints);
- myCbToSkipResultsWhenOneUsage = createCheckbox(FindSettings.getInstance().isSkipResultsWithOneUsage(), FindBundle.message("find.options.skip.results.tab.with.one.usage.checkbox"));
+ myCbToSkipResultsWhenOneUsage = createCheckbox(FindSettings.getInstance().isSkipResultsWithOneUsage(), FindBundle.message("find.options.skip.results.tab.with.one.occurrence.checkbox"));
optionsPanel.add(myCbToSkipResultsWhenOneUsage, gbConstraints);
- myCbToSkipResultsWhenOneUsage.setVisible(myModel.isReplaceState());
+ myCbToSkipResultsWhenOneUsage.setVisible(!myModel.isReplaceState());
}
else {
if (FindManagerImpl.ourHasSearchInCommentsAndLiterals) {
@@ -476,6 +471,9 @@ public class FindDialog extends DialogWrapper {
findSettings.setWholeWordsOnly(myModel.isWholeWordsOnly());
findSettings.setInStringLiteralsOnly(myModel.isInStringLiteralsOnly());
findSettings.setInCommentsOnly(myModel.isInCommentsOnly());
+ findSettings.setExceptComments(myModel.isExceptComments());
+ findSettings.setExceptStringLiterals(myModel.isExceptStringLiterals());
+ findSettings.setExceptCommentsAndLiterals(myModel.isExceptCommentsAndStringLiterals());
findSettings.setRegularExpressions(myModel.isRegularExpressions());
if (!myModel.isMultipleFiles()){
@@ -603,39 +601,26 @@ public class FindDialog extends DialogWrapper {
regExPanel.setLayout(new BoxLayout(regExPanel, BoxLayout.X_AXIS));
regExPanel.add(myCbRegularExpressions);
- regExPanel.add(new LinkLabel("[Help]", null, new LinkListener() {
- @Override
- public void linkSelected(LinkLabel aSource, Object aLinkData) {
- try {
- final JBPopup helpPopup = RegExHelpPopup.createRegExHelpPopup();
- helpPopup.showInCenterOf(regExPanel);
- }
- catch (BadLocationException e) {
- LOG.info(e);
- }
- }
- }));
+ regExPanel.add(RegExHelpPopup.createRegExLink("[Help]", regExPanel, LOG));
findOptionsPanel.add(regExPanel);
- myCbInCommentsOnly = createCheckbox(FindBundle.message("find.options.comments.only"));
- myCbInStringLiteralsOnly = createCheckbox(FindBundle.message("find.options.string.literals.only"));
- ItemListener itemListener = new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- if (e.getSource() == myCbInCommentsOnly) {
- if (myCbInCommentsOnly.isSelected()) myCbInStringLiteralsOnly.setSelected(false);
- } else if (e.getSource() == myCbInStringLiteralsOnly) {
- if (myCbInStringLiteralsOnly.isSelected()) myCbInCommentsOnly.setSelected(false);
- }
- }
- };
- myCbInCommentsOnly.addItemListener(itemListener);
- myCbInStringLiteralsOnly.addItemListener(itemListener);
+ mySearchContext = new ComboBox(new Object[] {FindBundle.message("find.context.anywhere.scope.label", 200),
+ FindBundle.message("find.context.in.comments.scope.label"), FindBundle.message("find.context.in.literals.scope.label"),
+ FindBundle.message("find.context.except.comments.scope.label"),
+ FindBundle.message("find.context.except.literals.scope.label"),
+ FindBundle.message("find.context.except.comments.and.literals.scope.label")});
+ final JPanel searchContextPanel = new JPanel(new BorderLayout());
+ searchContextPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ JLabel searchContextLabel = new JLabel(FindBundle.message("find.context.combo.label"));
+ searchContextLabel.setLabelFor(mySearchContext);
+ searchContextPanel.add(searchContextLabel, BorderLayout.WEST);
+
+ searchContextPanel.add(mySearchContext, BorderLayout.CENTER);
if (FindManagerImpl.ourHasSearchInCommentsAndLiterals) {
- findOptionsPanel.add(myCbInCommentsOnly);
- findOptionsPanel.add(myCbInStringLiteralsOnly);
+ findOptionsPanel.add(searchContextPanel);
}
ActionListener actionListener = new ActionListener() {
@@ -1000,9 +985,25 @@ public class FindDialog extends DialogWrapper {
}
model.setWholeWordsOnly(myCbWholeWordsOnly.isSelected());
- model.setInStringLiteralsOnly(myCbInStringLiteralsOnly.isSelected());
- model.setInCommentsOnly(myCbInCommentsOnly.isSelected());
+ String selectedSearchContextInUi = (String)mySearchContext.getSelectedItem();
+ FindModel.SearchContext searchContext = FindModel.SearchContext.ANY;
+ if (FindBundle.message("find.context.in.literals.scope.label").equals(selectedSearchContextInUi)) {
+ searchContext = FindModel.SearchContext.IN_STRING_LITERALS;
+ }
+ else if (FindBundle.message("find.context.in.comments.scope.label").equals(selectedSearchContextInUi)) {
+ searchContext = FindModel.SearchContext.IN_COMMENTS;
+ }
+ else if (FindBundle.message("find.context.except.comments.scope.label").equals(selectedSearchContextInUi)) {
+ searchContext = FindModel.SearchContext.EXCEPT_COMMENTS;
+ }
+ else if (FindBundle.message("find.context.except.literals.scope.label").equals(selectedSearchContextInUi)) {
+ searchContext = FindModel.SearchContext.EXCEPT_STRING_LITERALS;
+ } else if (FindBundle.message("find.context.except.comments.and.literals.scope.label").equals(selectedSearchContextInUi)) {
+ searchContext = FindModel.SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS;
+ }
+
+ model.setSearchContext(searchContext);
model.setRegularExpressions(myCbRegularExpressions.isSelected());
String stringToFind = getStringToFind();
@@ -1068,8 +1069,14 @@ public class FindDialog extends DialogWrapper {
private void initByModel() {
myCbCaseSensitive.setSelected(myModel.isCaseSensitive());
myCbWholeWordsOnly.setSelected(myModel.isWholeWordsOnly());
- myCbInStringLiteralsOnly.setSelected(myModel.isInStringLiteralsOnly());
- myCbInCommentsOnly.setSelected(myModel.isInCommentsOnly());
+ String searchContext = FindBundle.message("find.context.anywhere.scope.label");
+ if (myModel.isInCommentsOnly()) searchContext = FindBundle.message("find.context.in.comments.scope.label");
+ else if (myModel.isInStringLiteralsOnly()) searchContext = FindBundle.message("find.context.in.literals.scope.label");
+ else if (myModel.isExceptStringLiterals()) searchContext = FindBundle.message("find.context.except.literals.scope.label");
+ else if (myModel.isExceptComments()) searchContext = FindBundle.message("find.context.except.comments.scope.label");
+ else if (myModel.isExceptCommentsAndStringLiterals()) searchContext = FindBundle.message("find.context.except.comments.and.literals.scope.label");
+ mySearchContext.setSelectedItem(searchContext);
+
myCbRegularExpressions.setSelected(myModel.isRegularExpressions());
if (myModel.isMultipleFiles()) {
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
index 59adf1e62bd0..7e9e71d7a94d 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java
@@ -19,6 +19,7 @@ import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import com.intellij.find.FindBundle;
import com.intellij.find.FindModel;
+import com.intellij.find.findInProject.FindInProjectManager;
import com.intellij.find.ngrams.TrigramIndex;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
@@ -182,7 +183,7 @@ class FindInProjectTask {
private void searchInFiles(@NotNull Collection<PsiFile> psiFiles,
@NotNull FindUsagesProcessPresentation processPresentation,
- @NotNull Processor<UsageInfo> consumer) {
+ @NotNull final Processor<UsageInfo> consumer) {
int i = 0;
long totalFilesSize = 0;
int count = 0;
@@ -195,7 +196,8 @@ class FindInProjectTask {
long fileLength = UsageViewManagerImpl.getFileLength(virtualFile);
if (fileLength == -1) continue; // Binary or invalid
- if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !Registry.is("find.search.in.project.files")) continue;
+ final boolean skipProjectFile = ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile) && !myFindModel.isSearchInProjectFiles();
+ if (skipProjectFile && !Registry.is("find.search.in.project.files")) continue;
if (fileLength > SINGLE_FILE_SIZE_LIMIT) {
myLargeFiles.add(psiFile);
@@ -209,7 +211,24 @@ class FindInProjectTask {
myProgress.setText(text);
myProgress.setText2(FindBundle.message("find.searching.for.string.in.file.occurrences.progress", count));
- int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, consumer);
+ int countInFile = FindInProjectUtil.processUsagesInFile(psiFile, myFindModel, new Processor<UsageInfo>() {
+ @Override
+ public boolean process(UsageInfo info) {
+ return skipProjectFile || consumer.process(info);
+ }
+ });
+
+ if (countInFile > 0 && skipProjectFile) {
+ processPresentation.projectFileUsagesFound(new Runnable() {
+ @Override
+ public void run() {
+ FindModel model = myFindModel.clone();
+ model.setSearchInProjectFiles(true);
+ FindInProjectManager.getInstance(myProject).startFindInProject(model);
+ }
+ });
+ continue;
+ }
count += countInFile;
if (countInFile > 0) {
@@ -231,6 +250,7 @@ class FindInProjectTask {
final GlobalSearchScope globalCustomScope = toGlobal(customScope);
final ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(myProject);
+ final boolean hasTrigrams = hasTrigrams(myFindModel.getStringToFind());
class EnumContentIterator implements ContentIterator {
final Set<PsiFile> myFiles = new LinkedHashSet<PsiFile>();
@@ -238,8 +258,6 @@ class FindInProjectTask {
@Override
public boolean processFile(@NotNull final VirtualFile virtualFile) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
- final boolean hasTrigrams = hasTrigrams(myFindModel.getStringToFind());
-
@Override
public void run() {
ProgressManager.checkCanceled();
@@ -249,9 +267,6 @@ class FindInProjectTask {
return;
}
- if (virtualFile.getFileType().isBinary()) {
- return;
- }
if (skipIndexed && isCoveredByIndex(virtualFile) &&
(fileIndex.isInContent(virtualFile) || fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile))) {
return;
@@ -261,7 +276,9 @@ class FindInProjectTask {
if (psiFile != null && !(psiFile instanceof PsiBinaryFile) && !alreadySearched.contains(psiFile)) {
PsiFile sourceFile = (PsiFile)psiFile.getNavigationElement();
if (sourceFile != null) psiFile = sourceFile;
- myFiles.add(psiFile);
+ if (!psiFile.getFileType().isBinary()) {
+ myFiles.add(psiFile);
+ }
}
}
@@ -290,7 +307,9 @@ class FindInProjectTask {
for (VirtualFile file : getLocalScopeFiles((LocalSearchScope)customScope)) {
iterator.processFile(file);
}
- } else if (customScope instanceof Iterable) { // GlobalSearchScope can span files out of project roots e.g. FileScope / FilesScope
+ }
+ else if (customScope instanceof Iterable) { // GlobalSearchScope can span files out of project roots e.g. FileScope / FilesScope
+ //noinspection unchecked
for (VirtualFile file : (Iterable<VirtualFile>)customScope) {
iterator.processFile(file);
}
@@ -382,16 +401,14 @@ class FindInProjectTask {
return myFindModel.isWholeWordsOnly() && text.indexOf('$') < 0 && !StringUtil.getWordsInStringLongestFirst(text).isEmpty();
}
- private static boolean hasTrigrams(String text) {
- if (TrigramIndex.ENABLED) {
- return !TrigramBuilder.processTrigrams(text, new TrigramBuilder.TrigramProcessor() {
- @Override
- public boolean execute(int value) {
- return false;
- }
- });
- }
- return false;
+ private static boolean hasTrigrams(@NotNull String text) {
+ return TrigramIndex.ENABLED &&
+ !TrigramBuilder.processTrigrams(text, new TrigramBuilder.TrigramProcessor() {
+ @Override
+ public boolean execute(int value) {
+ return false;
+ }
+ });
}
@@ -430,6 +447,7 @@ class FindInProjectTask {
final List<VirtualFile> hits = new ArrayList<VirtualFile>();
final GlobalSearchScope finalScope = scope;
ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
public void run() {
FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor<VirtualFile>(hits),
finalScope);
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
index e4570b7379bf..23f14c5eb0b4 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
@@ -47,7 +47,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.ex.VirtualFileManagerEx;
import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.ui.content.Content;
@@ -55,7 +54,6 @@ import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewManager;
import com.intellij.usages.ConfigurableUsageTarget;
import com.intellij.usages.FindUsagesProcessPresentation;
-import com.intellij.usages.UsageView;
import com.intellij.usages.UsageViewPresentation;
import com.intellij.util.Function;
import com.intellij.util.PatternUtil;
@@ -326,7 +324,7 @@ public class FindInProjectUtil {
return processPresentation;
}
- public static class StringUsageTarget implements ConfigurableUsageTarget, ItemPresentation, TypeSafeDataProvider {
+ public static class StringUsageTarget implements ConfigurableUsageTarget, ItemPresentation {
@NotNull protected final Project myProject;
@NotNull protected final FindModel myFindModel;
@@ -425,12 +423,5 @@ public class FindInProjectUtil {
public KeyboardShortcut getShortcut() {
return ActionManager.getInstance().getKeyboardShortcut("FindInPath");
}
-
- @Override
- public void calcData(DataKey key, DataSink sink) {
- if (key == UsageView.USAGE_SCOPE) {
- sink.put(UsageView.USAGE_SCOPE, GlobalSearchScope.allScope(myProject));
- }
- }
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
index e327ec79c227..27e2b7215f25 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
@@ -27,7 +27,6 @@ import com.intellij.find.impl.livePreview.SearchResults;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageParserDefinitions;
import com.intellij.lang.ParserDefinition;
-import com.intellij.lexer.LayeredLexer;
import com.intellij.lexer.Lexer;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.actionSystem.ActionManager;
@@ -42,11 +41,6 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.ex.FoldingModelEx;
-import com.intellij.openapi.editor.ex.util.LayeredHighlighterIterator;
-import com.intellij.openapi.editor.ex.util.LayeredLexerEditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
-import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.TextEditor;
@@ -58,15 +52,17 @@ import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
-import com.intellij.psi.impl.search.LexerEditorHighlighterLexer;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.ui.LightweightHint;
import com.intellij.ui.ReplacePromptDialog;
+import com.intellij.usages.ChunkExtractor;
import com.intellij.usages.UsageViewManager;
+import com.intellij.usages.impl.SyntaxHighlighterOverEditorHighlighter;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.Predicate;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.text.StringSearcher;
@@ -96,6 +92,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
private final FindUsagesManager myFindUsagesManager;
private boolean isFindWasPerformed = false;
+ private boolean isSelectNextOccurrenceWasPerformed = false;
private Point myReplaceInFilePromptPos = new Point(-1, -1);
private Point myReplaceInProjectPromptPos = new Point(-1, -1);
private final FindModel myFindInProjectModel = new FindModel();
@@ -257,7 +254,18 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
@Override
public void setFindWasPerformed() {
isFindWasPerformed = true;
- //myFindUsagesManager.clearFindingNextUsageInFile();
+ isSelectNextOccurrenceWasPerformed = false;
+ }
+
+ @Override
+ public boolean selectNextOccurrenceWasPerformed() {
+ return isSelectNextOccurrenceWasPerformed;
+ }
+
+ @Override
+ public void setSelectNextOccurrenceWasPerformed() {
+ isSelectNextOccurrenceWasPerformed = true;
+ isFindWasPerformed = false;
}
@Override
@@ -270,7 +278,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
if (myFindNextModel == null) return null;
final JComponent header = editor.getHeaderComponent();
- if (header instanceof EditorSearchComponent) {
+ if (header instanceof EditorSearchComponent && !isSelectNextOccurrenceWasPerformed) {
final EditorSearchComponent searchComponent = (EditorSearchComponent)header;
final String textInField = searchComponent.getTextInField();
if (!Comparing.equal(textInField, myFindInFileModel.getStringToFind()) && !textInField.isEmpty()) {
@@ -305,25 +313,103 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
LOG.debug(model.toString());
}
- final char[] textArray = CharArrayUtil.fromSequenceWithoutCopying(text);
+ return findStringLoop(text, offset, model, file, getFindContextPredicate(model, file, text));
+ }
+ private FindResult findStringLoop(CharSequence text, int offset, FindModel model, VirtualFile file, @Nullable Predicate<FindResult> filter) {
+ final char[] textArray = CharArrayUtil.fromSequenceWithoutCopying(text);
while(true) {
FindResult result = doFindString(text, textArray, offset, model, file);
+ if (filter == null || filter.apply(result)) {
+ if (!model.isWholeWordsOnly()) {
+ return result;
+ }
+ if (!result.isStringFound()) {
+ return result;
+ }
+ if (isWholeWord(text, result.getStartOffset(), result.getEndOffset())) {
+ return result;
+ }
+ }
+
+ offset = model.isForward() ? result.getStartOffset() + 1 : result.getEndOffset() - 1;
+ if (offset > text.length() || offset < 0) return NOT_FOUND_RESULT;
+ }
+ }
+
+ private class FindExceptCommentsOrLiteralsData implements Predicate<FindResult> {
+ private final VirtualFile myFile;
+ private final FindModel myFindModel;
+ private final TreeMap<Integer, Integer> mySkipRangesSet;
+
+ private FindExceptCommentsOrLiteralsData(VirtualFile file, FindModel model, CharSequence text) {
+ myFile = file;
+ myFindModel = model.clone();
- if (!model.isWholeWordsOnly()) {
- return result;
+ TreeMap<Integer, Integer> result = new TreeMap<Integer, Integer>();
+
+ if (model.isExceptComments() || model.isExceptCommentsAndStringLiterals()) {
+ addRanges(file, model, text, result, FindModel.SearchContext.IN_COMMENTS);
}
- if (!result.isStringFound()){
- return result;
+
+ if (model.isExceptStringLiterals() || model.isExceptCommentsAndStringLiterals()) {
+ addRanges(file, model, text, result, FindModel.SearchContext.IN_STRING_LITERALS);
}
- if (isWholeWord(text, result.getStartOffset(), result.getEndOffset())){
- return result;
+
+ mySkipRangesSet = result;
+ }
+
+ private void addRanges(VirtualFile file,
+ FindModel model,
+ CharSequence text,
+ TreeMap<Integer, Integer> result,
+ FindModel.SearchContext searchContext) {
+ FindModel clonedModel = model.clone();
+ clonedModel.setSearchContext(searchContext);
+ clonedModel.setForward(true);
+ int offset = 0;
+
+ while(true) {
+ FindResult customResult = findStringLoop(text, offset, clonedModel, file, null);
+ if (!customResult.isStringFound()) break;
+ result.put(customResult.getStartOffset(), customResult.getEndOffset());
+ offset = Math.max(customResult.getEndOffset(), offset + 1); // avoid loop for zero size reg exps matches
+ if (offset >= text.length()) break;
}
+ }
- offset = model.isForward() ? result.getStartOffset() + 1 : result.getEndOffset() - 1;
- if (offset > text.length() || offset < 0) return NOT_FOUND_RESULT;
+ boolean isAcceptableFor(FindModel model, VirtualFile file) {
+ return Comparing.equal(myFile, file) && myFindModel.equals(model);
+ }
+
+ @Override
+ public boolean apply(@Nullable FindResult input) {
+ if (input == null || !input.isStringFound()) return true;
+ NavigableMap<Integer, Integer> map = mySkipRangesSet.headMap(input.getStartOffset(), true);
+ for(Map.Entry<Integer, Integer> e:map.descendingMap().entrySet()) {
+ if (e.getKey() <= input.getStartOffset() && e.getValue() >= input.getEndOffset()) return false;
+ if (e.getValue() <= input.getStartOffset()) break;
+ }
+ return true;
}
}
+ private static Key<FindExceptCommentsOrLiteralsData> ourExceptCommentsOrLiteralsDataKey = Key.create("except.comments.literals.search.data");
+
+ private Predicate<FindResult> getFindContextPredicate(@NotNull FindModel model, VirtualFile file, CharSequence text) {
+ if (file == null) return null;
+ FindModel.SearchContext context = model.getSearchContext();
+ if( context == FindModel.SearchContext.ANY || context == FindModel.SearchContext.IN_COMMENTS ||
+ context == FindModel.SearchContext.IN_STRING_LITERALS) {
+ return null;
+ }
+
+ FindExceptCommentsOrLiteralsData data = model.getUserData(ourExceptCommentsOrLiteralsDataKey);
+ if (data == null || !data.isAcceptableFor(model, file)) {
+ model.putUserData(ourExceptCommentsOrLiteralsDataKey, data = new FindExceptCommentsOrLiteralsData(file, model, text));
+ }
+
+ return data;
+ }
@Override
public int showMalformedReplacementPrompt(@NotNull FindModel model, String title, MalformedReplacementStringException exception) {
@@ -408,11 +494,15 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
return new StringSearcher(model.getStringToFind(), model.isCaseSensitive(), model.isForward());
}
+ public static void clearPreviousFindData(FindModel model) {
+ model.putUserData(ourCommentsLiteralsSearchDataKey, null);
+ model.putUserData(ourExceptCommentsOrLiteralsDataKey, null);
+ }
+
private static class CommentsLiteralsSearchData {
final VirtualFile lastFile;
int startOffset = 0;
- final SyntaxHighlighter highlighter;
- final Lexer highlightingLexer;
+ final SyntaxHighlighterOverEditorHighlighter highlighter;
TokenSet tokensOfInterest;
final StringSearcher searcher;
@@ -420,8 +510,8 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
final Set<Language> relevantLanguages;
final FindModel model;
- public CommentsLiteralsSearchData(VirtualFile lastFile, Set<Language> relevantLanguages, SyntaxHighlighter highlighter,
- Lexer lexer, TokenSet tokensOfInterest,
+ public CommentsLiteralsSearchData(VirtualFile lastFile, Set<Language> relevantLanguages,
+ SyntaxHighlighterOverEditorHighlighter highlighter, TokenSet tokensOfInterest,
StringSearcher searcher, Matcher matcher, FindModel model) {
this.lastFile = lastFile;
this.highlighter = highlighter;
@@ -429,12 +519,11 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
this.searcher = searcher;
this.matcher = matcher;
this.relevantLanguages = relevantLanguages;
- highlightingLexer = lexer;
this.model = model;
}
}
- public static final Key<CommentsLiteralsSearchData> ourCommentsLiteralsSearchDataKey = Key.create("comments.literals.search.data");
+ private static final Key<CommentsLiteralsSearchData> ourCommentsLiteralsSearchDataKey = Key.create("comments.literals.search.data");
@NotNull
private FindResult findInCommentsAndLiterals(@NotNull CharSequence text,
@@ -512,38 +601,15 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
Matcher matcher = model.isRegularExpressions() ? compileRegExp(model, ""):null;
StringSearcher searcher = matcher != null ? null: new StringSearcher(model.getStringToFind(), model.isCaseSensitive(), true);
- LayeredLexer.ourDisableLayersFlag.set(Boolean.TRUE);
- EditorHighlighter editorHighlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(myProject, file);
- Lexer lexer;
-
- try {
- if (editorHighlighter instanceof LayeredLexerEditorHighlighter) {
- lexer = new LexerEditorHighlighterLexer(editorHighlighter, false);
- } else {
- lexer = highlighter.getHighlightingLexer();
- }
- }
- finally {
- LayeredLexer.ourDisableLayersFlag.set(null);
- }
-
- data = new CommentsLiteralsSearchData(file, relevantLanguages, highlighter, lexer, tokensOfInterest, searcher, matcher, (FindModel)model.clone());
- lexer.start(text, 0, text.length(), 0);
+ SyntaxHighlighterOverEditorHighlighter highlighterAdapter = new SyntaxHighlighterOverEditorHighlighter(highlighter, file, myProject);
+ data = new CommentsLiteralsSearchData(file, relevantLanguages, highlighterAdapter, tokensOfInterest, searcher, matcher, model.clone());
+ data.highlighter.restart(text);
model.putUserData(ourCommentsLiteralsSearchDataKey, data);
}
int initialStartOffset = model.isForward() && data.startOffset < offset ? data.startOffset : 0;
- final Lexer lexer = data.highlightingLexer;
- LayeredHighlighterIterator layeredHighlighterIterator = null;
- if (lexer instanceof LexerEditorHighlighterLexer) {
- ((LexerEditorHighlighterLexer)lexer).resetPosition(initialStartOffset);
- HighlighterIterator iterator = ((LexerEditorHighlighterLexer)lexer).getHighlighterIterator();
- if (iterator instanceof LayeredHighlighterIterator) {
- layeredHighlighterIterator = (LayeredHighlighterIterator)iterator;
- }
- } else {
- lexer.start(text, initialStartOffset, text.length(), 0);
- }
+ data.highlighter.resetPosition(initialStartOffset);
+ final Lexer lexer = data.highlighter.getHighlightingLexer();
IElementType tokenType;
TokenSet tokens = data.tokensOfInterest;
@@ -555,13 +621,11 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
while((tokenType = lexer.getTokenType()) != null) {
if (lexer.getState() == 0) lastGoodOffset = lexer.getTokenStart();
- final SyntaxHighlighter activeSyntaxHighlighter =
- layeredHighlighterIterator != null ? layeredHighlighterIterator.getActiveSyntaxHighlighter() : data.highlighter;
- final TextAttributesKey[] keys = activeSyntaxHighlighter.getTokenHighlights(tokenType);
+ final TextAttributesKey[] keys = data.highlighter.getTokenHighlights(tokenType);
if (tokens.contains(tokenType) ||
- (model.isInStringLiteralsOnly() && isHighlightedAsString(keys)) ||
- (model.isInCommentsOnly() && isHighlightedAsDocComment(keys))
+ (model.isInStringLiteralsOnly() && ChunkExtractor.isHighlightedAsString(keys)) ||
+ (model.isInCommentsOnly() && ChunkExtractor.isHighlightedAsComment(keys))
) {
int start = lexer.getTokenStart();
int end = lexer.getTokenEnd();
@@ -634,32 +698,6 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
return prevFindResult;
}
- private static boolean isHighlightedAsDocComment(TextAttributesKey... keys) {
- for (TextAttributesKey key : keys) {
- if (key == DefaultLanguageHighlighterColors.DOC_COMMENT || key == SyntaxHighlighterColors.DOC_COMMENT) {
- return true;
- }
- final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
- if (fallbackAttributeKey != null && isHighlightedAsDocComment(fallbackAttributeKey)) {
- return true;
- }
- }
- return false;
- }
-
- private static boolean isHighlightedAsString(TextAttributesKey... keys) {
- for (TextAttributesKey key : keys) {
- if (key == DefaultLanguageHighlighterColors.STRING || key == SyntaxHighlighterColors.STRING) {
- return true;
- }
- final TextAttributesKey fallbackAttributeKey = key.getFallbackAttributeKey();
- if (fallbackAttributeKey != null && isHighlightedAsString(fallbackAttributeKey)) {
- return true;
- }
- }
- return false;
- }
-
private static TokenSet addTokenTypesForLanguage(FindModel model, Language lang, TokenSet tokensOfInterest) {
ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(lang);
if (definition != null) {
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java b/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
index 2c372795ea85..ee8d98422250 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
@@ -80,7 +80,7 @@ public class FindResultUsageInfo extends UsageInfo {
Long data = myFindModel.getUserData(ourDocumentTimestampKey);
if (data == null || data != myTimestamp) {
data = myTimestamp;
- myFindModel.putUserData(FindManagerImpl.ourCommentsLiteralsSearchDataKey, null);
+ FindManagerImpl.clearPreviousFindData(myFindModel);
}
myFindModel.putUserData(ourDocumentTimestampKey, data);
FindResult result;
@@ -110,7 +110,13 @@ public class FindResultUsageInfo extends UsageInfo {
assert result.isStringFound();
- if (myFindModel.isRegularExpressions() || myFindModel.isInCommentsOnly() || myFindModel.isInStringLiteralsOnly()) {
+ if (myFindModel.isRegularExpressions() ||
+ myFindModel.isInCommentsOnly() ||
+ myFindModel.isInStringLiteralsOnly() ||
+ myFindModel.isExceptStringLiterals() ||
+ myFindModel.isExceptCommentsAndStringLiterals() ||
+ myFindModel.isExceptComments()
+ ) {
myAnchor = SmartPointerManager.getInstance(getProject()).createSmartPsiFileRangePointer(file, TextRange.from(offset, 0));
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
index 5fb74f190ac0..c9c8e3492834 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindSettingsImpl.java
@@ -103,6 +103,9 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom
@SuppressWarnings({"WeakerAccess"}) public boolean WHOLE_WORDS_ONLY = false;
@SuppressWarnings({"WeakerAccess"}) public boolean COMMENTS_ONLY = false;
@SuppressWarnings({"WeakerAccess"}) public boolean STRING_LITERALS_ONLY = false;
+ @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_COMMENTS = false;
+ @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_COMMENTS_AND_STRING_LITERALS = false;
+ @SuppressWarnings({"WeakerAccess"}) public boolean EXCEPT_STRING_LITERALS = false;
@SuppressWarnings({"WeakerAccess"}) public boolean LOCAL_WHOLE_WORDS_ONLY = false;
@SuppressWarnings({"WeakerAccess"}) public boolean REGULAR_EXPRESSIONS = false;
@SuppressWarnings({"WeakerAccess"}) public boolean LOCAL_REGULAR_EXPRESSIONS = false;
@@ -276,8 +279,18 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom
model.setGlobal(isGlobal());
model.setRegularExpressions(isRegularExpressions());
model.setWholeWordsOnly(isWholeWordsOnly());
- model.setInCommentsOnly(isInCommentsOnly());
- model.setInStringLiteralsOnly(isInStringLiteralsOnly());
+ FindModel.SearchContext searchContext = isInCommentsOnly() ?
+ FindModel.SearchContext.IN_COMMENTS :
+ isInStringLiteralsOnly() ?
+ FindModel.SearchContext.IN_STRING_LITERALS :
+ isExceptComments() ?
+ FindModel.SearchContext.EXCEPT_COMMENTS :
+ isExceptStringLiterals() ?
+ FindModel.SearchContext.EXCEPT_STRING_LITERALS :
+ isExceptCommentsAndLiterals() ?
+ FindModel.SearchContext.EXCEPT_COMMENTS_AND_STRING_LITERALS :
+ FindModel.SearchContext.ANY;
+ model.setSearchContext(searchContext);
model.setWithSubdirectories(isWithSubdirectories());
model.setFileFilter(FILE_MASK);
@@ -384,4 +397,34 @@ public class FindSettingsImpl extends FindSettings implements PersistentStateCom
public void setCustomScope(final String SEARCH_SCOPE) {
this.SEARCH_SCOPE = SEARCH_SCOPE;
}
+
+ @Override
+ public boolean isExceptComments() {
+ return EXCEPT_COMMENTS;
+ }
+
+ @Override
+ public void setExceptCommentsAndLiterals(boolean selected) {
+ EXCEPT_COMMENTS_AND_STRING_LITERALS = selected;
+ }
+
+ @Override
+ public boolean isExceptCommentsAndLiterals() {
+ return EXCEPT_COMMENTS_AND_STRING_LITERALS;
+ }
+
+ @Override
+ public void setExceptComments(boolean selected) {
+ EXCEPT_COMMENTS = selected;
+ }
+
+ @Override
+ public boolean isExceptStringLiterals() {
+ return EXCEPT_STRING_LITERALS;
+ }
+
+ @Override
+ public void setExceptStringLiterals(boolean selected) {
+ EXCEPT_STRING_LITERALS = selected;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java b/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java
index 23dee12e362f..0aace901a409 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/RegExHelpPopup.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.
@@ -17,12 +17,19 @@ package com.intellij.find.impl;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.ide.BrowserUtil;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.popup.ComponentPopupBuilder;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.util.MinimizeButton;
+import com.intellij.openapi.util.Disposer;
import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.components.labels.LinkLabel;
+import com.intellij.ui.components.labels.LinkListener;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
@@ -331,6 +338,36 @@ public class RegExHelpPopup extends JPanel {
add(myScrollPane, BorderLayout.CENTER);
}
+ @NotNull
+ public static LinkLabel createRegExLink(@NotNull String title, @Nullable final Component owner, @Nullable final Logger logger) {
+ return new LinkLabel(title, null, new LinkListener() {
+ JBPopup helpPopup;
+ @Override
+ public void linkSelected(LinkLabel aSource, Object aLinkData) {
+ try {
+ if (helpPopup != null && !helpPopup.isDisposed() && helpPopup.isVisible()) {
+ return;
+ }
+ helpPopup = createRegExHelpPopup();
+ Disposer.register(helpPopup, new Disposable() {
+ @Override
+ public void dispose() {
+ destroyPopup();
+ }
+ });
+ helpPopup.showInCenterOf(owner);
+ }
+ catch (BadLocationException e) {
+ if (logger != null) logger.info(e);
+ }
+ }
+
+ private void destroyPopup() {
+ helpPopup = null;
+ }
+ });
+ }
+
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 300);
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java b/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java
index e9e8c130a6f4..f5417dfb5a25 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatterEx.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatterEx.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.
@@ -116,7 +116,14 @@ public abstract class FormatterEx{
TextRange affectedRange);
public abstract void setProgressTask(@NotNull FormattingProgressTask progressIndicator);
-
+
+ /**
+ * Calculates minimum spacing, allowed by formatting model (in columns) for a block starting at given offset,
+ * relative to its previous sibling block.
+ * Returns zero, if required block cannot be found at provided offset, or spacing cannot be calculated due to some other reason.
+ */
+ public abstract int getSpacingForBlockAtOffset(FormattingModel model, int offset);
+
public interface IndentInfoStorage {
void saveIndentInfo(@Nullable IndentInfo info, int startOffset);
diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
index e1366431efd0..7b40b786ff7a 100644
--- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
+++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java
@@ -25,6 +25,7 @@ import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
@@ -109,6 +110,58 @@ public class FormatterImpl extends FormatterEx
}
@Override
+ public int getSpacingForBlockAtOffset(FormattingModel model, int offset) {
+ Couple<Block> blockWithParent = getBlockAtOffset(null, model.getRootBlock(), offset);
+ if (blockWithParent == null) {
+ return 0;
+ }
+ Block parentBlock = blockWithParent.first;
+ Block targetBlock = blockWithParent.second;
+ if (parentBlock == null || targetBlock == null) {
+ return 0;
+ }
+ Block prevBlock = findPreviousSibling(parentBlock, targetBlock);
+ if (prevBlock == null) {
+ return 0;
+ }
+ SpacingImpl spacing = (SpacingImpl)parentBlock.getSpacing(prevBlock, targetBlock);
+ if (spacing == null) {
+ return 0;
+ }
+ return Math.max(spacing.getMinSpaces(), 0);
+ }
+
+ private static Couple<Block> getBlockAtOffset(Block parent, Block block, int offset) {
+ TextRange textRange = block.getTextRange();
+ int startOffset = textRange.getStartOffset();
+ int endOffset = textRange.getEndOffset();
+ if (startOffset == offset) {
+ return Couple.of(parent, block);
+ }
+ if (startOffset > offset || endOffset < offset || block.isLeaf()) {
+ return null;
+ }
+ for (Block subBlock : block.getSubBlocks()) {
+ Couple<Block> result = getBlockAtOffset(block, subBlock, offset);
+ if (result != null) {
+ return result;
+ }
+ }
+ return null;
+ }
+
+ private static Block findPreviousSibling(Block parent, Block block) {
+ Block result = null;
+ for (Block subBlock : parent.getSubBlocks()) {
+ if (subBlock == block) {
+ return result;
+ }
+ result = subBlock;
+ }
+ return null;
+ }
+
+ @Override
public void format(final FormattingModel model, final CodeStyleSettings settings,
final CommonCodeStyleSettings.IndentOptions indentOptions,
final CommonCodeStyleSettings.IndentOptions javaIndentOptions,
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
index 88d675b168de..6239cbbab4ac 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.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.
@@ -28,17 +28,21 @@ import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.components.JBList;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -66,15 +70,33 @@ public class DetectionExcludesConfigurable implements Configurable {
@NotNull
public JComponent createComponent() {
myEnabledDetectionCheckBox = new JCheckBox("Enable framework detection");
+ myEnabledDetectionCheckBox.setBorder(new EmptyBorder(10, 10, 0, 0));
final JBList excludesList = new JBList(myModel);
- excludesList.setCellRenderer(new ColoredListCellRenderer() {
+ final ColoredListCellRenderer renderer = new ColoredListCellRenderer() {
+ JPanel panel = new JPanel(new BorderLayout());
+ {
+ panel.setBorder(new EmptyBorder(2, 10, 2, 0));
+ panel.add(this);
+ }
+
@Override
protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
+ setIconTextGap(4);
if (value instanceof ExcludeListItem) {
((ExcludeListItem)value).renderItem(this);
+ setBorder(new EmptyBorder(0, 10, 0, 0));
}
}
- });
+
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean selected, boolean hasFocus) {
+ super.getListCellRendererComponent(list, value, index, selected, hasFocus);
+ panel.setBackground(UIUtil.getListBackground(selected));
+ return panel;
+ }
+ };
+ renderer.setMyBorder(new EmptyBorder(0,0,0,0));
+ excludesList.setCellRenderer(renderer);
final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(excludesList)
.disableUpAction().disableDownAction()
.setAddAction(new AnActionButtonRunnable() {
@@ -83,9 +105,12 @@ public class DetectionExcludesConfigurable implements Configurable {
doAddAction(button);
}
});
+ if (Registry.is("ide.new.project.settings")) {
+ decorator.setPanelBorder(new CustomLineBorder(1, 0, 0, 0));
+ }
myMainPanel = new JPanel(new BorderLayout(0, 5));
myMainPanel.add(myEnabledDetectionCheckBox, BorderLayout.NORTH);
- final LabeledComponent<JPanel> excludesComponent = LabeledComponent.create(decorator.createPanel(), "Exclude from detection:");
+ final LabeledComponent<JPanel> excludesComponent = LabeledComponent.create(decorator.createPanel(), " Exclude from detection:");
myMainPanel.add(excludesComponent);
myEnabledDetectionCheckBox.addActionListener(new ActionListener() {
@Override
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java
index 6848b039ceed..0dcdde7c6297 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/InvalidExcludeListItem.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.
@@ -17,6 +17,7 @@ package com.intellij.framework.detection.impl.exclude;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.util.ui.EmptyIcon;
/**
* @author nik
@@ -51,6 +52,7 @@ class InvalidExcludeListItem extends ExcludeListItem {
else {
renderer.append(myFileUrl, SimpleTextAttributes.ERROR_ATTRIBUTES);
}
+ renderer.setIcon(EmptyIcon.ICON_16);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
index 6d734d52a584..e86caec534f6 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java
@@ -15,6 +15,7 @@
*/
package com.intellij.ide.actions;
+import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.navigation.GotoRelatedItem;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.ui.popup.JBPopup;
@@ -25,22 +26,25 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
- * @deprecated API compatibility. Utility methods will be moved to NavigationUtil
+ * @deprecated API compatibility. Utility methods moved to NavigationUtil.
+ * todo [neuro] REMOVE-ME when September Ends..
* @author gregsh
*/
public class GotoRelatedFileAction {
/**
- * @deprecated This method will be moved to NavigationUtil
+ * @deprecated
+ * @see com.intellij.codeInsight.navigation.NavigationUtil#getRelatedItemsPopup(java.util.List, String)
*/
public static JBPopup createPopup(List<? extends GotoRelatedItem> items, final String title) {
- return GotoRelatedSymbolAction.createPopup(items, title);
+ return NavigationUtil.getRelatedItemsPopup(items, title);
}
/**
- * @deprecated This method will be moved to NavigationUtil
+ * @deprecated
+ * @see com.intellij.codeInsight.navigation.NavigationUtil#collectRelatedItems(com.intellij.psi.PsiElement, com.intellij.openapi.actionSystem.DataContext)
*/
public static List<GotoRelatedItem> getItems(@NotNull PsiElement contextElement, @Nullable DataContext dataContext) {
- return GotoRelatedSymbolAction.getItems(contextElement, dataContext);
+ return NavigationUtil.collectRelatedItems(contextElement, dataContext);
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java
index 2870f806ab8a..229531b3ef53 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedSymbolAction.java
@@ -15,39 +15,19 @@
*/
package com.intellij.ide.actions;
-import com.intellij.ide.util.DefaultPsiElementCellRenderer;
+import com.intellij.codeInsight.navigation.NavigationUtil;
import com.intellij.navigation.GotoRelatedItem;
-import com.intellij.navigation.GotoRelatedProvider;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.ui.popup.JBPopup;
-import com.intellij.openapi.ui.popup.PopupStep;
-import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
-import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
-import com.intellij.ui.ColoredListCellRenderer;
-import com.intellij.ui.JBColor;
-import com.intellij.ui.SeparatorWithText;
-import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.ui.popup.list.ListPopupImpl;
-import com.intellij.ui.popup.list.PopupListElementRenderer;
-import com.intellij.util.Processor;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.util.*;
import java.util.List;
/**
@@ -66,210 +46,20 @@ public class GotoRelatedSymbolAction extends AnAction {
PsiElement element = getContextElement(e.getDataContext());
if (element == null) return;
- List<GotoRelatedItem> items = getItems(element, e.getDataContext());
+ List<GotoRelatedItem> items = NavigationUtil.collectRelatedItems(element, e.getDataContext());
if (items.isEmpty()) return;
if (items.size() == 1 && items.get(0).getElement() != null) {
items.get(0).navigate();
return;
}
- createPopup(items, "Choose Target").showInBestPositionFor(e.getDataContext());
- }
-
- public static JBPopup createPopup(final List<? extends GotoRelatedItem> items, final String title) {
- Object[] elements = new Object[items.size()];
- //todo[nik] move presentation logic to GotoRelatedItem class
- final Map<PsiElement, GotoRelatedItem> itemsMap = new HashMap<PsiElement, GotoRelatedItem>();
- for (int i = 0; i < items.size(); i++) {
- GotoRelatedItem item = items.get(i);
- elements[i] = item.getElement() != null ? item.getElement() : item;
- itemsMap.put(item.getElement(), item);
- }
-
- return getPsiElementPopup(elements, itemsMap, title, new Processor<Object>() {
- @Override
- public boolean process(Object element) {
- if (element instanceof PsiElement) {
- //noinspection SuspiciousMethodCalls
- itemsMap.get(element).navigate();
- }
- else {
- ((GotoRelatedItem)element).navigate();
- }
- return true;
- }
- }
- );
- }
-
- private static JBPopup getPsiElementPopup(final Object[] elements, final Map<PsiElement, GotoRelatedItem> itemsMap,
- final String title, final Processor<Object> processor) {
-
- final Ref<Boolean> hasMnemonic = Ref.create(false);
- final DefaultPsiElementCellRenderer renderer = new DefaultPsiElementCellRenderer() {
- {
- setFocusBorderEnabled(false);
- }
-
- @Override
- public String getElementText(PsiElement element) {
- String customName = itemsMap.get(element).getCustomName();
- return (customName != null ? customName : super.getElementText(element));
- }
-
- @Override
- protected Icon getIcon(PsiElement element) {
- Icon customIcon = itemsMap.get(element).getCustomIcon();
- return customIcon != null ? customIcon : super.getIcon(element);
- }
-
- @Override
- public String getContainerText(PsiElement element, String name) {
- String customContainerName = itemsMap.get(element).getCustomContainerName();
-
- if (customContainerName != null) {
- return customContainerName;
- }
- PsiFile file = element.getContainingFile();
- return file != null && !getElementText(element).equals(file.getName())
- ? "(" + file.getName() + ")"
- : null;
- }
-
- @Override
- protected DefaultListCellRenderer getRightCellRenderer(Object value) {
- return null;
- }
-
- @Override
- protected boolean customizeNonPsiElementLeftRenderer(ColoredListCellRenderer renderer,
- JList list,
- Object value,
- int index,
- boolean selected,
- boolean hasFocus) {
- final GotoRelatedItem item = (GotoRelatedItem)value;
- Color color = list.getForeground();
- final SimpleTextAttributes nameAttributes = new SimpleTextAttributes(Font.PLAIN, color);
- final String name = item.getCustomName();
- if (name == null) return false;
- renderer.append(name, nameAttributes);
- renderer.setIcon(item.getCustomIcon());
- return true;
- }
-
- @Override
- public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
- final JPanel component = (JPanel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
- if (!hasMnemonic.get()) return component;
-
- final JPanel panelWithMnemonic = new JPanel(new BorderLayout());
- final int mnemonic = getMnemonic(value, itemsMap);
- final JLabel label = new JLabel("");
- if (mnemonic != -1) {
- label.setText(mnemonic + ".");
- label.setDisplayedMnemonicIndex(0);
- }
- label.setPreferredSize(new JLabel("8.").getPreferredSize());
-
- final JComponent leftRenderer = (JComponent)component.getComponents()[0];
- component.remove(leftRenderer);
- panelWithMnemonic.setBorder(BorderFactory.createEmptyBorder(0, 7, 0, 0));
- panelWithMnemonic.setBackground(leftRenderer.getBackground());
- label.setBackground(leftRenderer.getBackground());
- panelWithMnemonic.add(label, BorderLayout.WEST);
- panelWithMnemonic.add(leftRenderer, BorderLayout.CENTER);
- component.add(panelWithMnemonic);
- return component;
- }
- };
- final ListPopupImpl popup = new ListPopupImpl(new BaseListPopupStep<Object>(title, Arrays.asList(elements)) {
- @Override
- public boolean isSpeedSearchEnabled() {
- return true;
- }
-
- @Override
- public String getIndexedString(Object value) {
- if (value instanceof GotoRelatedItem) {
- //noinspection ConstantConditions
- return ((GotoRelatedItem)value).getCustomName();
- }
- final PsiElement element = (PsiElement)value;
- return renderer.getElementText(element) + " " + renderer.getContainerText(element, null);
- }
-
- @Override
- public PopupStep onChosen(Object selectedValue, boolean finalChoice) {
- processor.process(selectedValue);
- return super.onChosen(selectedValue, finalChoice);
- }
- }) {
- };
- popup.getList().setCellRenderer(new PopupListElementRenderer(popup) {
- Map<Object, String> separators = new HashMap<Object, String>();
- {
- final ListModel model = popup.getList().getModel();
- String current = null;
- boolean hasTitle = false;
- for (int i = 0; i < model.getSize(); i++) {
- final Object element = model.getElementAt(i);
- final GotoRelatedItem item = itemsMap.get(element);
- if (item != null && !StringUtil.equals(current, item.getGroup())) {
- current = item.getGroup();
- separators.put(element, current);
- if (!hasTitle && !StringUtil.isEmpty(current)) {
- hasTitle = true;
- }
- }
- }
-
- if (!hasTitle) {
- separators.remove(model.getElementAt(0));
- }
- }
- @Override
- public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
- final Component component = renderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
- final String separator = separators.get(value);
-
- if (separator != null) {
- JPanel panel = new JPanel(new BorderLayout());
- panel.add(component, BorderLayout.CENTER);
- final SeparatorWithText sep = new SeparatorWithText() {
- @Override
- protected void paintComponent(Graphics g) {
- g.setColor(new JBColor(Color.WHITE, UIUtil.getSeparatorColor()));
- g.fillRect(0,0,getWidth(), getHeight());
- super.paintComponent(g);
- }
- };
- sep.setCaption(separator);
- panel.add(sep, BorderLayout.NORTH);
- return panel;
- }
- return component;
- }
- });
-
- popup.setMinimumSize(new Dimension(200, -1));
-
- for (Object item : elements) {
- final int mnemonic = getMnemonic(item, itemsMap);
- if (mnemonic != -1) {
- final Action action = createNumberAction(mnemonic, popup, itemsMap, processor);
- popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke(String.valueOf(mnemonic)), action);
- popup.registerAction(mnemonic + "Action", KeyStroke.getKeyStroke("NUMPAD" + String.valueOf(mnemonic)), action);
- hasMnemonic.set(true);
- }
- }
- return popup;
+ NavigationUtil.getRelatedItemsPopup(items, "Choose Target").showInBestPositionFor(e.getDataContext());
}
@TestOnly
@NotNull
public static List<GotoRelatedItem> getItems(@NotNull PsiFile psiFile, @Nullable Editor editor, @Nullable DataContext dataContext) {
- return getItems(getContextElement(psiFile, editor), dataContext);
+ return NavigationUtil.collectRelatedItems(getContextElement(psiFile, editor), dataContext);
}
@Nullable
@@ -294,65 +84,4 @@ public class GotoRelatedSymbolAction extends AnAction {
}
return contextElement;
}
-
- @NotNull
- public static List<GotoRelatedItem> getItems(@NotNull PsiElement contextElement, @Nullable DataContext dataContext) {
- Set<GotoRelatedItem> items = ContainerUtil.newLinkedHashSet();
- for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) {
- items.addAll(provider.getItems(contextElement));
- if (dataContext != null) {
- items.addAll(provider.getItems(dataContext));
- }
- }
- sortByGroupNames(items);
- return new ArrayList<GotoRelatedItem>(items);
- }
-
- private static void sortByGroupNames(Set<GotoRelatedItem> items) {
- Map<String, List<GotoRelatedItem>> map = new HashMap<String, List<GotoRelatedItem>>();
- for (GotoRelatedItem item : items) {
- final String key = item.getGroup();
- if (!map.containsKey(key)) {
- map.put(key, new ArrayList<GotoRelatedItem>());
- }
- map.get(key).add(item);
- }
- final List<String> keys = new ArrayList<String>(map.keySet());
- Collections.sort(keys, new Comparator<String>() {
- @Override
- public int compare(String o1, String o2) {
- return StringUtil.isEmpty(o1) ? 1 : StringUtil.isEmpty(o2) ? -1 : o1.compareTo(o2);
- }
- });
- items.clear();
- for (String key : keys) {
- items.addAll(map.get(key));
- }
- }
-
- private static Action createNumberAction(final int mnemonic,
- final ListPopupImpl listPopup,
- final Map<PsiElement, GotoRelatedItem> itemsMap,
- final Processor<Object> processor) {
- return new AbstractAction() {
- @Override
- public void actionPerformed(ActionEvent e) {
- for (final Object item : listPopup.getListStep().getValues()) {
- if (getMnemonic(item, itemsMap) == mnemonic) {
- listPopup.setFinalRunnable(new Runnable() {
- @Override
- public void run() {
- processor.process(item);
- }
- });
- listPopup.closeOk(null);
- }
- }
- }
- };
- }
-
- private static int getMnemonic(Object item, Map<PsiElement, GotoRelatedItem> itemsMap) {
- return (item instanceof GotoRelatedItem ? (GotoRelatedItem)item : itemsMap.get((PsiElement)item)).getMnemonic();
- }
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java
index 3e28023a935c..531f3e52159f 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchAgainAction.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.
@@ -49,7 +49,8 @@ public class SearchAgainAction extends AnAction implements DumbAware {
public void run() {
PsiDocumentManager.getInstance(project).commitAllDocuments();
IdeDocumentHistory.getInstance(project).includeCurrentCommandAsNavigation();
- if(FindManager.getInstance(project).findNextUsageInEditor(editor)) {
+ FindManager findManager = FindManager.getInstance(project);
+ if(!findManager.selectNextOccurrenceWasPerformed() && findManager.findNextUsageInEditor(editor)) {
return;
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java
index 4783205ae8c0..5f6e0d9959bd 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchBackAction.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.
@@ -46,7 +46,8 @@ public class SearchBackAction extends AnAction implements DumbAware {
@Override
public void run() {
PsiDocumentManager.getInstance(project).commitAllDocuments();
- if(FindManager.getInstance(project).findPreviousUsageInEditor(editor)) {
+ FindManager findManager = FindManager.getInstance(project);
+ if(!findManager.selectNextOccurrenceWasPerformed() && findManager.findPreviousUsageInEditor(editor)) {
return;
}
FindUtil.searchBack(project, editor, e.getDataContext());
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
index ae7ee4363247..d704e738efa3 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
@@ -108,11 +108,9 @@ import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.*;
-import java.lang.reflect.Field;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
/**
* @author Konstantin Bulenkov
@@ -2120,13 +2118,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
private SearchListModel() {
super();
- try {
- final Field field = DefaultListModel.class.getDeclaredField("delegate");
- field.setAccessible(true);
- myDelegate = (Vector)field.get(this);
- }
- catch (NoSuchFieldException ignore) {}
- catch (IllegalAccessException ignore) {}
+ myDelegate = ReflectionUtil.getField(DefaultListModel.class, this, Vector.class, "delegate");
}
int next(int index) {
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
index bb80f55237e5..c4708c48d19f 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
@@ -29,6 +29,7 @@ import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.impl.nodes.AbstractModuleNode;
import com.intellij.ide.projectView.impl.nodes.AbstractProjectNode;
import com.intellij.ide.projectView.impl.nodes.ModuleGroupNode;
+import com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode;
import com.intellij.ide.util.treeView.*;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.openapi.Disposable;
@@ -54,6 +55,7 @@ import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.move.MoveHandler;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ReflectionUtil;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
@@ -481,6 +483,27 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl
}
public PsiDirectory[] getSelectedDirectories() {
+ List<PsiDirectory> directories = ContainerUtil.newArrayList();
+ for (PsiDirectoryNode node : getSelectedNodes(PsiDirectoryNode.class)) {
+ PsiDirectory directory = node.getValue();
+ if (directory != null) {
+ directories.add(directory);
+ Object parentValue = node.getParent().getValue();
+ if (parentValue instanceof PsiDirectory) {
+ while (true) {
+ directory = directory.getParentDirectory();
+ if (directory == null || directory.equals(parentValue)) {
+ break;
+ }
+ directories.add(directory);
+ }
+ }
+ }
+ }
+ if (!directories.isEmpty()) {
+ return directories.toArray(new PsiDirectory[directories.size()]);
+ }
+
final PsiElement[] elements = getSelectedPSIElements();
if (elements.length == 1) {
final PsiElement element = elements[0];
diff --git a/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java b/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java
index 2aa89adeb3b5..2a6c396e1e3e 100644
--- a/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/todo/ChangeListTodosPanel.java
@@ -65,7 +65,12 @@ public abstract class ChangeListTodosPanel extends TodoPanel{
@Override
public void changeListRenamed(final ChangeList list, final String oldName) {
- setDisplayName(IdeBundle.message("changelist.todo.title", list.getName()));
+ AppUIUtil.invokeOnEdt(new Runnable() {
+ @Override
+ public void run() {
+ setDisplayName(IdeBundle.message("changelist.todo.title", list.getName()));
+ }
+ });
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
index f260c732adf5..35f7f658edfd 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
@@ -65,6 +65,7 @@ import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure;
import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.HashSet;
@@ -83,7 +84,6 @@ import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.*;
-import java.lang.reflect.Field;
import java.util.*;
import java.util.List;
@@ -1018,22 +1018,13 @@ public class FileStructurePopup implements Disposable {
public FileStructureTree(Object rootElement, boolean fastExpand) {
super(new DefaultMutableTreeNode(rootElement));
if (fastExpand) {
- boolean newValueIsSet;
- try {
- final Field field = JTree.class.getDeclaredField("expandedState");
- field.setAccessible(true);
- field.set(this, new Hashtable() {
- @Override
- public synchronized Object get(Object key) {
- return Boolean.TRUE;
- }
- });
- newValueIsSet = true;
- }
- catch (Exception e) {
- newValueIsSet = false;
- }
- fast = newValueIsSet;
+ Hashtable hashtable = new Hashtable() {
+ @Override
+ public synchronized Object get(Object key) {
+ return Boolean.TRUE;
+ }
+ };
+ fast = ReflectionUtil.setField(JTree.class, this, Hashtable.class, "expandedState", hashtable);
}
else {
fast = false;
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
index dcc1429c8bbd..3e90f2310884 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
@@ -35,6 +35,7 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationAdapter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.fileTypes.UnknownFileType;
@@ -102,6 +103,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class ChooseByNameBase {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.gotoByName.ChooseByNameBase");
protected final Project myProject;
protected final ChooseByNameModel myModel;
protected ChooseByNameItemProvider myProvider;
@@ -133,7 +135,6 @@ public abstract class ChooseByNameBase {
private final ListUpdater myListUpdater = new ListUpdater();
- private volatile boolean myListIsUpToDate = false;
private boolean myDisposedFlag = false;
private ActionCallback myPostponedOkAction;
@@ -278,7 +279,7 @@ public abstract class ChooseByNameBase {
if (PlatformDataKeys.HELP_ID.is(dataId)) {
return myModel.getHelpId();
}
- if (!myListIsUpToDate) {
+ if (myCalcElementsThread != null) {
return null;
}
if (CommonDataKeys.PSI_ELEMENT.is(dataId)) {
@@ -499,7 +500,7 @@ public abstract class ChooseByNameBase {
myTextField.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(@NotNull final FocusEvent e) {
- cancelCalcElementsThread(); // cancel thread as early as possible
+ cancelListUpdater(); // cancel thread as early as possible
myHideAlarm.addRequest(new Runnable() {
@Override
public void run() {
@@ -531,7 +532,7 @@ public abstract class ChooseByNameBase {
if (queue instanceof IdeEventQueue) {
if (!((IdeEventQueue)queue).wasRootRecentlyClicked(oppositeComponent)) {
Component root = SwingUtilities.getRoot(myTextField);
- if (root != null) {
+ if (root != null && root.isShowing()) {
root.requestFocus();
myTextField.requestFocus();
return;
@@ -759,24 +760,29 @@ public abstract class ChooseByNameBase {
}
protected void doClose(final boolean ok) {
- try {
- if (checkDisposed()) return;
+ if (checkDisposed()) return;
- if (postponeCloseWhenListReady(ok)) return;
+ if (postponeCloseWhenListReady(ok)) return;
- cancelListUpdater();
- close(ok);
+ cancelListUpdater();
+ close(ok);
- clearPostponedOkAction(ok);
- }
- finally {
- myListModel.clear();
- cancelCalcElementsThread();
- }
+ clearPostponedOkAction(ok);
+ myListModel.clear();
}
protected void cancelListUpdater() {
- cancelCalcElementsThread();
+ final CalcElementsThread calcElementsThread = myCalcElementsThread;
+ if (calcElementsThread != null && calcElementsThread.cancel()) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ if (!checkDisposed() && calcElementsThread == myCalcElementsThread) {
+ backgroundCalculationFinished(Collections.emptyList(), 0);
+ }
+ }
+ });
+ }
myListUpdater.cancelAll();
}
@@ -784,7 +790,7 @@ public abstract class ChooseByNameBase {
if (!isToFixLostTyping()) return false;
final String text = myTextField.getText();
- if (ok && !myListIsUpToDate && text != null && !text.trim().isEmpty()) {
+ if (ok && myCalcElementsThread != null && text != null && !text.trim().isEmpty()) {
myPostponedOkAction = new ActionCallback();
IdeFocusManager.getInstance(myProject).typeAheadUntil(myPostponedOkAction);
return true;
@@ -885,7 +891,7 @@ public abstract class ChooseByNameBase {
Disposer.register(myTextPopup, new Disposable() {
@Override
public void dispose() {
- cancelCalcElementsThread();
+ cancelListUpdater();
}
});
myTextPopup.show(layeredPane);
@@ -917,8 +923,6 @@ public abstract class ChooseByNameBase {
return layeredPane;
}
- private final Object myRebuildMutex = new Object();
-
protected void rebuildList(final int pos,
final int delay,
@NotNull final ModalityState modalityState,
@@ -928,11 +932,13 @@ public abstract class ChooseByNameBase {
return;
}
- myListIsUpToDate = false;
myAlarm.cancelAllRequests();
myListUpdater.cancelAll();
- cancelCalcElementsThread();
+ final CalcElementsThread calcElementsThread = myCalcElementsThread;
+ if (calcElementsThread != null) {
+ calcElementsThread.cancel();
+ }
final String text = myTextField.getText();
if (!canShowListForEmptyPattern() &&
@@ -960,24 +966,14 @@ public abstract class ChooseByNameBase {
scheduleCalcElements(text, myCheckBox.isSelected(), modalityState, new Consumer<Set<?>>() {
@Override
public void consume(Set<?> elements) {
- synchronized (myRebuildMutex) {
- ApplicationManager.getApplication().assertIsDispatchThread();
- if (checkDisposed()) {
- return;
- }
-
- myListIsUpToDate = true;
- setElementsToList(pos, elements);
- myList.repaint();
- chosenElementMightChange();
-
- if (elements.isEmpty()) {
- myTextFieldPanel.hideHint();
- }
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ if (checkDisposed()) {
+ return;
+ }
+ backgroundCalculationFinished(elements, pos);
- if (postRunnable != null) {
- postRunnable.run();
- }
+ if (postRunnable != null) {
+ postRunnable.run();
}
}
});
@@ -992,6 +988,17 @@ public abstract class ChooseByNameBase {
}
}
+ private void backgroundCalculationFinished(Collection<?> result, int toSelect) {
+ myCalcElementsThread = null;
+ setElementsToList(toSelect, result);
+ myList.repaint();
+ chosenElementMightChange();
+
+ if (result.isEmpty()) {
+ myTextFieldPanel.hideHint();
+ }
+ }
+
public void scheduleCalcElements(String text,
boolean checkboxState,
ModalityState modalityState,
@@ -1008,16 +1015,7 @@ public abstract class ChooseByNameBase {
return myShowListAfterCompletionKeyStroke;
}
- private CalcElementsThread cancelCalcElementsThread() {
- CalcElementsThread calcElementsThread = myCalcElementsThread;
- if (calcElementsThread != null) {
- calcElementsThread.cancel();
- myCalcElementsThread = null;
- }
- return calcElementsThread;
- }
-
- private void setElementsToList(int pos, @NotNull Set<?> elements) {
+ private void setElementsToList(int pos, @NotNull Collection<?> elements) {
myListUpdater.cancelAll();
if (checkDisposed()) return;
if (elements.isEmpty()) {
@@ -1202,33 +1200,12 @@ public abstract class ChooseByNameBase {
}
protected List<Object> getChosenElements() {
-
- List<Object> values = new ArrayList<Object>(Arrays.asList(myList.getSelectedValues()));
- values.remove(EXTRA_ELEM);
- values.remove(NON_PREFIX_SEPARATOR);
-
- if (myListIsUpToDate || !values.isEmpty()) {
- return values;
- }
-
- final String text = myTextField.getText();
- if (text.length() == 0) return Collections.emptyList();
- final boolean checkBoxState = myCheckBox.isSelected();
- final String[] names = ourLoadNamesEachTime ? ensureNamesLoaded(checkBoxState) : getNamesSync(checkBoxState);
- if (names == null) return Collections.emptyList();
-
- Object uniqueElement = null;
-
- for (final String name : names) {
- if (text.equalsIgnoreCase(name)) {
- final Object[] elements = myModel.getElementsByName(name, checkBoxState, text);
- if (elements.length > 1) return Collections.emptyList();
- if (elements.length == 0) continue;
- if (uniqueElement != null) return Collections.emptyList();
- uniqueElement = elements[0];
+ return ContainerUtil.filter(myList.getSelectedValues(), new Condition<Object>() {
+ @Override
+ public boolean value(Object o) {
+ return o != EXTRA_ELEM && o != NON_PREFIX_SEPARATOR;
}
- }
- return uniqueElement == null ? Collections.emptyList() : Collections.singletonList(uniqueElement);
+ });
}
protected void chosenElementMightChange() {
@@ -1565,6 +1542,7 @@ public abstract class ChooseByNameBase {
@Override
public void run() {
if (!myCancelled.isCanceled()) {
+ LOG.assertTrue(myCalcElementsThread == CalcElementsThread.this);
myCallback.consume(edt ? filter(elements) : filtered);
}
}
@@ -1622,8 +1600,12 @@ public abstract class ChooseByNameBase {
return elementsArray.size() >= myMaximumListSizeLimit;
}
- private void cancel() {
+ private boolean cancel() {
+ if (myCancelled.isCanceled()) {
+ return false;
+ }
myCancelled.cancel();
+ return true;
}
}
@@ -1705,7 +1687,7 @@ public abstract class ChooseByNameBase {
final LinkedHashSet<Object> nonPrefixMatchElementsArray = new LinkedHashSet<Object>();
hideHint();
ProgressManager.getInstance().run(new Task.Modal(myProject, prefixPattern, true) {
- private ChooseByNameBase.CalcElementsThread myCalcElementsThread;
+ private ChooseByNameBase.CalcElementsThread myCalcUsagesThread;
@Override
public void run(@NotNull final ProgressIndicator indicator) {
@@ -1716,7 +1698,7 @@ public abstract class ChooseByNameBase {
@Override
public void run() {
final boolean[] overFlow = {false};
- myCalcElementsThread = new CalcElementsThread(text, everywhere, null, ModalityState.NON_MODAL, false) {
+ myCalcUsagesThread = new CalcElementsThread(text, everywhere, null, ModalityState.NON_MODAL, false) {
private final AtomicBoolean userAskedToAbort = new AtomicBoolean();
@Override
protected boolean isOverflow(@NotNull Set<Object> elementsArray) {
@@ -1734,11 +1716,11 @@ public abstract class ChooseByNameBase {
boolean anyPlace = isSearchInAnyPlace();
setSearchInAnyPlace(false);
- myCalcElementsThread.addElementsByPattern(text, prefixMatchElementsArray, indicator, everywhere);
+ myCalcUsagesThread.addElementsByPattern(text, prefixMatchElementsArray, indicator, everywhere);
setSearchInAnyPlace(anyPlace);
if (anyPlace && !overFlow[0]) {
- myCalcElementsThread.addElementsByPattern(text, nonPrefixMatchElementsArray, indicator, everywhere);
+ myCalcUsagesThread.addElementsByPattern(text, nonPrefixMatchElementsArray, indicator, everywhere);
nonPrefixMatchElementsArray.removeAll(prefixMatchElementsArray);
}
@@ -1756,7 +1738,7 @@ public abstract class ChooseByNameBase {
@Override
public void onCancel() {
- cancelCalcElementsThread();
+ myCalcUsagesThread.cancel();
}
});
}
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java
index cb03b68bfadb..86d9c1782b2a 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNamePopup.java
@@ -339,7 +339,7 @@ public class ChooseByNamePopup extends ChooseByNameBase implements ChooseByNameP
}
private static final Pattern patternToDetectLinesAndColumns = Pattern.compile("([^:]+)(?::|@|,|)\\[?(\\d+)?(?:(?:\\D)(\\d+)?)?\\]?");
- private static final Pattern patternToDetectAnonymousClasses = Pattern.compile("([\\.\\w]+)((\\$[\\d]+)*(\\$)?)");
+ public static final Pattern patternToDetectAnonymousClasses = Pattern.compile("([\\.\\w]+)((\\$[\\d]+)*(\\$)?)");
private static final Pattern patternToDetectMembers = Pattern.compile("(.+)(#)(.*)");
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
index aa6a360c84e5..cc5915c26bb6 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
@@ -189,6 +189,7 @@ public class DefaultChooseByNameItemProvider implements ChooseByNameItemProvider
@NotNull
private static String getQualifierPattern(@NotNull ChooseByNameBase base, @NotNull String pattern) {
+ pattern = base.transformPattern(pattern);
final String[] separators = base.getModel().getSeparators();
int lastSeparatorOccurrence = 0;
for (String separator : separators) {
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java
index a6e6c8fdf658..99d3c9b338ae 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionItemProvider.java
@@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
@@ -128,17 +129,19 @@ public class GotoActionItemProvider implements ChooseByNameItemProvider {
List<AnAction> actions = ContainerUtil.newArrayList();
if (everywhere) {
for (String id : ((ActionManagerImpl)myActionManager).getActionIds()) {
+ ProgressManager.checkCanceled();
ContainerUtil.addIfNotNull(actions, myActionManager.getAction(id));
}
} else {
- actions.addAll(myModel.myActionsMap.keySet());
+ actions.addAll(myModel.myActionGroups.keySet());
}
List<ActionWrapper> actionWrappers = ContainerUtil.newArrayList();
for (AnAction action : actions) {
+ ProgressManager.checkCanceled();
MatchMode mode = myModel.actionMatches(pattern, action);
if (mode != MatchMode.NONE) {
- actionWrappers.add(new ActionWrapper(action, myModel.myActionsMap.get(action), mode, dataContext));
+ actionWrappers.add(new ActionWrapper(action, myModel.myActionGroups.get(action), mode, dataContext));
}
}
return processItems(pattern, actionWrappers, consumer);
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
index 91f0d3368521..348283dc3885 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
@@ -66,16 +66,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
private Pattern myCompiledPattern;
protected final SearchableOptionsRegistrar myIndex;
- protected final Map<AnAction, String> myActionsMap = new TreeMap<AnAction, String>(new Comparator<AnAction>() {
- @Override
- public int compare(@NotNull AnAction o1, @NotNull AnAction o2) {
- int compare = Comparing.compare(o1.getTemplatePresentation().getText(), o2.getTemplatePresentation().getText());
- if (compare == 0 && !o1.equals(o2)) {
- return o1.hashCode() - o2.hashCode();
- }
- return compare;
- }
- });
+ protected final Map<AnAction, String> myActionGroups = ContainerUtil.newHashMap();
protected final Map<String, ApplyIntentionAction> myIntentions = new TreeMap<String, ApplyIntentionAction>();
private final Map<String, String> myConfigurablesNames = ContainerUtil.newTroveMap();
@@ -88,7 +79,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
myProject = project;
myContextComponent = component;
final ActionGroup mainMenu = (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU);
- collectActions(myActionsMap, mainMenu, mainMenu.getTemplatePresentation().getText());
+ collectActions(myActionGroups, mainMenu, mainMenu.getTemplatePresentation().getText());
if (project != null && editor != null && file != null) {
final ApplyIntentionAction[] children = ApplyIntentionAction.getAvailableIntentions(editor, file);
if (children != null) {
@@ -98,6 +89,9 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
}
}
myIndex = SearchableOptionsRegistrar.getInstance();
+ if (!EventQueue.isDispatchThread()) {
+ return;
+ }
fillConfigurablesNames(ShowSettingsUtilImpl.getConfigurables(project, true));
}
@@ -457,11 +451,14 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
else if (description != null && !description.equals(text) && matcher.matches(description, compiledPattern)) {
return MatchMode.DESCRIPTION;
}
- final String groupName = myActionsMap.get(anAction);
+ if (text == null) {
+ return MatchMode.NONE;
+ }
+ final String groupName = myActionGroups.get(anAction);
if (groupName == null) {
- return text != null && matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE;
+ return matcher.matches(text, compiledPattern) ? MatchMode.NON_MENU : MatchMode.NONE;
}
- return text != null && matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE;
+ return matcher.matches(groupName + " " + text, compiledPattern) ? MatchMode.GROUP : MatchMode.NONE;
}
@Nullable
@@ -611,7 +608,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, C
PatternMatcher getMatcher() {
return myMatcher.get();
}
-
+
public static class ActionWrapper implements Comparable<ActionWrapper>{
private final AnAction myAction;
private final MatchMode myMode;
diff --git a/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java b/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java
index 63d8a6038b6a..6350642c772e 100644
--- a/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java
+++ b/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java
@@ -22,7 +22,6 @@ import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -53,7 +52,12 @@ public class DumpLookupElementWeights extends AnAction implements DumbAware {
}
public static void dumpLookupElementWeights(final LookupImpl lookup) {
- String sb = StringUtil.join(getLookupElementWeights(lookup), "\n");
+ LookupElement selected = lookup.getCurrentItem();
+ String sb = "selected: " + selected;
+ if (selected != null) {
+ sb += "\nprefix: " + lookup.itemPattern(selected);
+ }
+ sb += "\nweights:\n" + StringUtil.join(getLookupElementWeights(lookup), "\n");
System.out.println(sb);
LOG.info(sb);
}
diff --git a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
index ad322c232fa0..ccf63a429346 100644
--- a/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
+++ b/platform/lang-impl/src/com/intellij/lang/parser/GeneratedParserUtilBase.java
@@ -100,8 +100,7 @@ public class GeneratedParserUtilBase {
if (!goodMarker) return false;
ErrorState state = ErrorState.get(builder_);
- Frame frame = state.frameStack.peekLast();
- return frame == null || frame.errorReportedAt <= builder_.rawTokenIndex();
+ return !state.frameStack.isEmpty();
}
public static TokenSet create_token_set_(IElementType... tokenTypes_) {
@@ -399,6 +398,11 @@ public class GeneratedParserUtilBase {
private static void enter_section_impl_(PsiBuilder builder_, int level, int modifiers, @Nullable String frameName) {
ErrorState state = ErrorState.get(builder_);
Frame frame = state.FRAMES.alloc().init(builder_, state, level, modifiers, frameName);
+ Frame prevFrame = state.frameStack.peekLast();
+ if (prevFrame != null && prevFrame.errorReportedAt > frame.position) {
+ // report error for previous unsuccessful frame
+ reportError(builder_, state, frame, true, false);
+ }
if (((frame.modifiers & _LEFT_) | (frame.modifiers & _LEFT_INNER_)) != 0) {
PsiBuilder.Marker left = (PsiBuilder.Marker)builder_.getLatestDoneMarker();
if (invalid_left_marker_guard_(builder_, left, frameName)) {
@@ -456,10 +460,10 @@ public class GeneratedParserUtilBase {
state.clearVariants(true, frame.variantCount);
addVariantInner(state, initialPos, frame.name);
}
+ int lastErrorPos = getLastVariantPos(state, initialPos);
if (!state.suppressErrors && eatMore != null) {
state.suppressErrors = true;
final boolean eatMoreFlagOnce = !builder_.eof() && eatMore.parse(builder_, frame.level + 1);
- final int lastErrorPos = getLastVariantPos(state, initialPos);
boolean eatMoreFlag = eatMoreFlagOnce || !result && frame.position == initialPos && lastErrorPos > frame.position;
PsiBuilderImpl.ProductionMarker latestDoneMarker =
@@ -497,7 +501,7 @@ public class GeneratedParserUtilBase {
errorReported = reportError(builder_, state, frame, true, true);
parseAsTree(state, builder_, frame.level + 1, DUMMY_BLOCK, true, TOKEN_ADVANCER, eatMore);
}
- else if (eatMoreFlagOnce || (!result && frame.position != builder_.rawTokenIndex())) {
+ else if (eatMoreFlagOnce || (!result && frame.position != builder_.rawTokenIndex()) || frame.errorReportedAt > initialPos) {
errorReported = reportError(builder_, state, frame, true, false);
}
if (extensionMarker != null) {
@@ -512,10 +516,14 @@ public class GeneratedParserUtilBase {
}
else if (!result && pinned && frame.errorReportedAt < 0) {
// do not report if there are errors beyond current position
- if (getLastVariantPos(state, initialPos) == initialPos) {
+ if (lastErrorPos == initialPos) {
// do not force, inner recoverRoot might have skipped some tokens
reportError(builder_, state, frame, false, false);
}
+ else if (lastErrorPos > initialPos) {
+ // set error pos here as if it is reported for future reference
+ frame.errorReportedAt = lastErrorPos;
+ }
}
// propagate errorReportedAt up the stack to avoid duplicate reporting
Frame prevFrame = willFail && eatMore == null ? null : state.frameStack.peekLast();
@@ -607,7 +615,7 @@ public class GeneratedParserUtilBase {
return;
}
int position = builder_.rawTokenIndex();
- if (frame.errorReportedAt < position && getLastVariantPos(state, position) <= position) {
+ if (frame.errorReportedAt < position && getLastVariantPos(state, position + 1) <= position) {
reportError(builder_, state, frame, true, advance);
}
}
@@ -865,7 +873,7 @@ public class GeneratedParserUtilBase {
((modifiers & _LEFT_INNER_) != 0? "_LEFT_INNER_, ": "") +
((modifiers & _AND_) != 0? "_AND_, ": "") +
((modifiers & _NOT_) != 0? "_NOT_, ": "");
- return "<" + offset + ", " + mod + level + (errorReportedAt > -1 ? ", [" + errorReportedAt + "]" : "") + ">";
+ return String.format("{%s:%s:%d, %d, %s%s}", offset, position, level, errorReportedAt, mod, name);
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
index 3e284ff6b2cc..ae2a4dc0d53c 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectAllOccurrencesAction.java
@@ -42,8 +42,6 @@ public class SelectAllOccurrencesAction extends EditorAction {
@Override
public void doExecute(final Editor editor, @Nullable Caret c, DataContext dataContext) {
- if (executeEquivalentFindPanelAction(editor, dataContext)) return;
-
Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
boolean wholeWordsSearch = false;
@@ -88,10 +86,5 @@ public class SelectAllOccurrencesAction extends EditorAction {
}, caretShiftFromSelectionStart);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
-
- @Override
- protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
- return new SelectAllAction(searchComponent);
- }
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
index 7d3c408ee152..74390f15b149 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectNextOccurrenceAction.java
@@ -40,8 +40,6 @@ public class SelectNextOccurrenceAction extends EditorAction {
@Override
public void doExecute(Editor editor, @Nullable Caret c, DataContext dataContext) {
- if (executeEquivalentFindPanelAction(editor, dataContext)) return;
-
Caret caret = c == null ? editor.getCaretModel().getPrimaryCaret() : c;
TextRange wordSelectionRange = getSelectionRange(editor, caret);
boolean notFoundPreviously = getAndResetNotFoundStatus(editor);
@@ -56,7 +54,7 @@ public class SelectNextOccurrenceAction extends EditorAction {
FindModel model = getFindModel(selectedText, wholeWordSearch);
- findManager.setFindWasPerformed();
+ findManager.setSelectNextOccurrenceWasPerformed();
findManager.setFindNextModel(model);
int searchStartOffset = notFoundPreviously ? 0 : caret.getSelectionEnd();
@@ -84,10 +82,5 @@ public class SelectNextOccurrenceAction extends EditorAction {
}
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
-
- @Override
- protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
- return new AddOccurrenceAction(searchComponent);
- }
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
index 7b189281dfd0..1858ef53b3f5 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectOccurrencesActionHandler.java
@@ -107,25 +107,4 @@ abstract public class SelectOccurrencesActionHandler extends EditorActionHandler
model.setWholeWordsOnly(wholeWords);
return model;
}
-
- protected boolean executeEquivalentFindPanelAction(Editor editor, DataContext context) {
- if (editor.getHeaderComponent() instanceof EditorSearchComponent) {
- EditorSearchComponent searchComponent = (EditorSearchComponent)editor.getHeaderComponent();
- EditorHeaderAction action = getEquivalentFindPanelAction(searchComponent);
- if (action != null) {
- Presentation presentation = new Presentation();
- AnActionEvent event = new AnActionEvent(null, context, ActionPlaces.MAIN_MENU, presentation, ActionManager.getInstance(), 0);
- action.update(event);
- if (presentation.isEnabled()) {
- action.actionPerformed(event);
- return true;
- }
- }
- }
- return false;
- }
-
- protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
- return null;
- }
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
index fffff56b12dc..a5657ff89b27 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/UnselectPreviousOccurrenceAction.java
@@ -15,9 +15,6 @@
*/
package com.intellij.openapi.editor.actions;
-import com.intellij.find.EditorSearchComponent;
-import com.intellij.find.editorHeaderActions.EditorHeaderAction;
-import com.intellij.find.editorHeaderActions.RemoveOccurrenceAction;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
@@ -38,8 +35,6 @@ public class UnselectPreviousOccurrenceAction extends EditorAction {
@Override
public void doExecute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
- if (executeEquivalentFindPanelAction(editor, dataContext)) return;
-
if (editor.getCaretModel().getCaretCount() > 1) {
editor.getCaretModel().removeCaret(editor.getCaretModel().getPrimaryCaret());
}
@@ -49,10 +44,5 @@ public class UnselectPreviousOccurrenceAction extends EditorAction {
getAndResetNotFoundStatus(editor);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
-
- @Override
- protected EditorHeaderAction getEquivalentFindPanelAction(EditorSearchComponent searchComponent) {
- return new RemoveOccurrenceAction(searchComponent);
- }
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java
index 4fec39342090..c5fd5592b634 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/FontMapper.java
@@ -16,10 +16,10 @@
package com.intellij.openapi.editor.richcopy;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
-import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Locale;
@@ -46,20 +46,18 @@ public class FontMapper {
}
Method findFontMethod = Class.forName("sun.font.FontManager").getMethod("findFont2D", String.class, int.class, int.class);
for (String logicalFont : logicalFontsToMap) {
- String physicalFont = null;
Object font2D = findFontMethod.invoke(fontManager, logicalFont, Font.PLAIN, 0);
if (font2D == null) {
continue;
}
String fontClassName = font2D.getClass().getName();
+ String physicalFont = null;
if ("sun.font.CompositeFont".equals(fontClassName)) { // Windows and Linux case
Object physicalFontObject = Class.forName("sun.font.CompositeFont").getMethod("getSlotFont", int.class).invoke(font2D, 0);
physicalFont = (String)Class.forName("sun.font.Font2D").getMethod("getFamilyName", Locale.class).invoke(physicalFontObject, Locale.getDefault());
}
else if ("sun.font.CFont".equals(fontClassName)) { // MacOS case
- Field field = Class.forName("sun.font.CFont").getDeclaredField("nativeFontName");
- field.setAccessible(true);
- physicalFont = (String)field.get(font2D);
+ physicalFont = ReflectionUtil.getField(Class.forName("sun.font.CFont"), font2D, String.class, "nativeFontName");
}
if (physicalFont != null) {
logicalToPhysicalMapping.put(logicalFont, physicalFont);
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java
index 54406106b976..504496a27716 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/richcopy/TextWithMarkupProcessor.java
@@ -23,6 +23,7 @@ import com.intellij.ide.highlighter.HighlighterFactory;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.colors.FontPreferences;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.ex.DisposableIterator;
import com.intellij.openapi.editor.ex.MarkupModelEx;
@@ -418,7 +419,7 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
private MarkupIterator(@NotNull CharSequence charSequence, @NotNull RangeIterator rangeIterator, @NotNull EditorColorsScheme colorsScheme) {
myRangeIterator = rangeIterator;
- mySegmentIterator = new SegmentIterator(charSequence, colorsScheme.getEditorFontName(), colorsScheme.getEditorFontSize());
+ mySegmentIterator = new SegmentIterator(charSequence, colorsScheme.getFontPreferences());
}
public boolean atEnd() {
@@ -812,8 +813,7 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
private static class SegmentIterator {
private final CharSequence myCharSequence;
- private final String myDefaultFontFamilyName;
- private final int myFontSize;
+ private final FontPreferences myFontPreferences;
private int myCurrentStartOffset;
private int myCurrentOffset;
@@ -822,10 +822,9 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
private String myCurrentFontFamilyName;
private String myNextFontFamilyName;
- private SegmentIterator(CharSequence charSequence, String defaultFontFamilyName, int fontSize) {
+ private SegmentIterator(CharSequence charSequence, FontPreferences fontPreferences) {
myCharSequence = charSequence;
- myDefaultFontFamilyName = defaultFontFamilyName;
- myFontSize = fontSize;
+ myFontPreferences = fontPreferences;
}
public void reset(int startOffset, int endOffset, int fontStyle) {
@@ -843,9 +842,8 @@ public class TextWithMarkupProcessor extends CopyPastePostProcessor<RawTextWithM
myCurrentStartOffset = myCurrentOffset;
for (; myCurrentOffset < myEndOffset; myCurrentOffset++) {
FontInfo fontInfo = ComplementaryFontsRegistry.getFontAbleToDisplay(myCharSequence.charAt(myCurrentOffset),
- myFontSize,
myFontStyle,
- myDefaultFontFamilyName);
+ myFontPreferences);
String fontFamilyName = fontInfo.getFont().getFamily();
if (myCurrentFontFamilyName == null) {
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
index b1385686bc3a..09e489b3d1df 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
@@ -25,15 +25,14 @@ import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ModuleRootAdapter;
-import com.intellij.openapi.roots.ModuleRootEvent;
-import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.*;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
+import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
import com.intellij.util.containers.ConcurrentIntObjectMap;
import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap;
@@ -43,6 +42,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
public class DirectoryIndexImpl extends DirectoryIndex {
@@ -68,7 +69,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
});
}
- private void subscribeToFileChanges() {
+ protected void subscribeToFileChanges() {
myConnection.subscribe(FileTypeManager.TOPIC, new FileTypeListener.Adapter() {
@Override
public void fileTypesChanged(@NotNull FileTypeEvent event) {
@@ -98,7 +99,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
});
}
- private void markContentRootsForRefresh() {
+ protected void markContentRootsForRefresh() {
Module[] modules = ModuleManager.getInstance(myProject).getModules();
for (Module module : modules) {
VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
@@ -110,7 +111,7 @@ public class DirectoryIndexImpl extends DirectoryIndex {
}
}
- private void dispatchPendingEvents() {
+ protected void dispatchPendingEvents() {
myConnection.deliverImmediately();
}
@@ -124,24 +125,27 @@ public class DirectoryIndexImpl extends DirectoryIndex {
private RootIndex getRootIndex() {
RootIndex rootIndex = myRootIndex;
if (rootIndex == null) {
- myRootIndex = rootIndex = new RootIndex(myProject, new RootIndex.InfoCache() {
- // Upsource can't use int-mapping because different files may have the same id there
- private final ConcurrentIntObjectMap<DirectoryInfo> myInfoCache = new StripedLockIntObjectConcurrentHashMap<DirectoryInfo>();
- @Override
- public void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info) {
- myInfoCache.put(((NewVirtualFile)dir).getId(), info);
- }
-
- @Override
- public DirectoryInfo getCachedInfo(@NotNull VirtualFile dir) {
- return myInfoCache.get(((NewVirtualFile)dir).getId());
- }
- });
+ myRootIndex = rootIndex = new RootIndex(myProject, createRootInfoCache());
}
return rootIndex;
}
- @Override
+ protected RootIndex.InfoCache createRootInfoCache() {
+ return new RootIndex.InfoCache() {
+ // Upsource can't use int-mapping because different files may have the same id there
+ private final ConcurrentIntObjectMap<DirectoryInfo> myInfoCache = new StripedLockIntObjectConcurrentHashMap<DirectoryInfo>();
+ @Override
+ public void cacheInfo(@NotNull VirtualFile dir, @NotNull DirectoryInfo info) {
+ myInfoCache.put(((NewVirtualFile)dir).getId(), info);
+ }
+
+ @Override
+ public DirectoryInfo getCachedInfo(@NotNull VirtualFile dir) {
+ return myInfoCache.get(((NewVirtualFile)dir).getId());
+ }
+ };
+ }
+
@TestOnly
public void checkConsistency() {
getRootIndex().checkConsistency();
@@ -181,6 +185,21 @@ public class DirectoryIndexImpl extends DirectoryIndex {
return getRootIndex().getPackageName(dir);
}
+ @NotNull
+ @Override
+ public OrderEntry[] getOrderEntries(@NotNull DirectoryInfo info) {
+ checkAvailability();
+ return getRootIndex().getOrderEntries(info);
+ }
+
+ @TestOnly
+ void assertConsistency(DirectoryInfo info) {
+ OrderEntry[] entries = getOrderEntries(info);
+ for (int i = 1; i < entries.length; i++) {
+ assert RootIndex.BY_OWNER_MODULE.compare(entries[i - 1], entries[i]) <= 0;
+ }
+ }
+
private void checkAvailability() {
if (myDisposed) {
ProgressManager.checkCanceled();
@@ -188,4 +207,95 @@ public class DirectoryIndexImpl extends DirectoryIndex {
}
}
+ @NotNull
+ private static OrderEntry createFakeOrderEntry(@NotNull final Module ownerModule) {
+ return new OrderEntry() {
+ @NotNull
+ @Override
+ public VirtualFile[] getFiles(OrderRootType type) {
+ throw new IncorrectOperationException();
+ }
+
+ @NotNull
+ @Override
+ public String[] getUrls(OrderRootType rootType) {
+ throw new IncorrectOperationException();
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean isValid() {
+ throw new IncorrectOperationException();
+ }
+
+ @NotNull
+ @Override
+ public Module getOwnerModule() {
+ return ownerModule;
+ }
+
+ @Override
+ public <R> R accept(RootPolicy<R> policy, @Nullable R initialValue) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public int compareTo(@NotNull OrderEntry o) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ throw new IncorrectOperationException();
+ }
+ };
+ }
+
+ @Override
+ @Nullable
+ OrderEntry findOrderEntryWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule) {
+ OrderEntry[] entries = getOrderEntries(info);
+ if (entries.length < 10) {
+ for (OrderEntry entry : entries) {
+ if (entry.getOwnerModule() == ownerModule) return entry;
+ }
+ return null;
+ }
+ int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), RootIndex.BY_OWNER_MODULE);
+ return index < 0 ? null : entries[index];
+ }
+
+ @Override
+ @NotNull
+ List<OrderEntry> findAllOrderEntriesWithOwnerModule(@NotNull DirectoryInfo info, @NotNull Module ownerModule) {
+ OrderEntry[] entries = getOrderEntries(info);
+ if (entries.length == 0) return Collections.emptyList();
+
+ if (entries.length == 1) {
+ OrderEntry entry = entries[0];
+ return entry.getOwnerModule() == ownerModule ? Arrays.asList(entries) : Collections.<OrderEntry>emptyList();
+ }
+ int index = Arrays.binarySearch(entries, createFakeOrderEntry(ownerModule), RootIndex.BY_OWNER_MODULE);
+ if (index < 0) {
+ return Collections.emptyList();
+ }
+ int firstIndex = index;
+ while (firstIndex - 1 >= 0 && entries[firstIndex - 1].getOwnerModule() == ownerModule) {
+ firstIndex--;
+ }
+ int lastIndex = index + 1;
+ while (lastIndex < entries.length && entries[lastIndex].getOwnerModule() == ownerModule) {
+ lastIndex++;
+ }
+
+ OrderEntry[] subArray = new OrderEntry[lastIndex - firstIndex];
+ System.arraycopy(entries, firstIndex, subArray, 0, lastIndex - firstIndex);
+
+ return Arrays.asList(subArray);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
index 932204c6dbd3..4ba8b7b03a8d 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
@@ -72,10 +72,8 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl {
private Set<LocalFileSystem.WatchRequest> myRootsToWatch = new THashSet<LocalFileSystem.WatchRequest>();
private final boolean myDoLogCachesUpdate;
- public ProjectRootManagerComponent(Project project,
- DirectoryIndex directoryIndex,
- StartupManager startupManager) {
- super(project, directoryIndex);
+ public ProjectRootManagerComponent(Project project, StartupManager startupManager) {
+ super(project);
myConnection = project.getMessageBus().connect(project);
myConnection.subscribe(FileTypeManager.TOPIC, new FileTypeListener() {
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java
deleted file mode 100644
index dd72da957fa2..000000000000
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.roots.libraries.ui.impl;
-
-import com.intellij.ui.CheckboxTree;
-import com.intellij.ui.CheckedTreeNode;
-import com.intellij.ui.ClickListener;
-import com.intellij.ui.dualView.TreeTableView;
-import com.intellij.ui.treeStructure.treetable.ListTreeTableModelOnColumns;
-import com.intellij.ui.treeStructure.treetable.TreeTableTree;
-import com.intellij.util.ui.ColumnInfo;
-import com.intellij.util.ui.tree.TreeUtil;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.TreeModel;
-import javax.swing.tree.TreeNode;
-import javax.swing.tree.TreePath;
-import java.awt.*;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.Enumeration;
-
-/**
- * @author nik
- */
-public class CheckboxTreeTable extends TreeTableView {
- public CheckboxTreeTable(CheckedTreeNode root, CheckboxTree.CheckboxTreeCellRenderer renderer, final ColumnInfo[] columns) {
- super(new ListTreeTableModelOnColumns(root, columns));
- initTree(getTree(), renderer);
- }
-
- //todo[nik] I hate to copy-paste but have to copy the code below from CheckboxTreeBase to support CheckboxTree inside TreeTable in IDEA 11.1.x branch
- //todo[nik] I solemnly swear to get rid of this code in IDEA 12 branch
- private void initTree(final TreeTableTree tree, final CheckboxTree.CheckboxTreeCellRenderer cellRenderer) {
- tree.setCellRenderer(cellRenderer);
- tree.setRootVisible(false);
- tree.setShowsRootHandles(true);
- tree.setLineStyleAngled();
- TreeUtil.installActions(tree);
-
- new ClickListener() {
- @Override
- public boolean onClick(@NotNull MouseEvent e, int clickCount) {
- int row = tree.getRowForLocation(e.getX(), e.getY());
- if (row < 0) return false;
- final Object o = tree.getPathForRow(row).getLastPathComponent();
- if (!(o instanceof CheckedTreeNode)) return false;
- Rectangle rowBounds = tree.getRowBounds(row);
- cellRenderer.setBounds(rowBounds);
- Rectangle checkBounds = cellRenderer.myCheckbox.getBounds();
- checkBounds.setLocation(rowBounds.getLocation());
-
- if (checkBounds.height == 0) checkBounds.height = rowBounds.height;
-
- final CheckedTreeNode node = (CheckedTreeNode)o;
- if (checkBounds.contains(e.getPoint())) {
- if (node.isEnabled()) {
- toggleNode(node);
- tree.setSelectionRow(row);
- return true;
- }
- }
-
- return false;
- }
- }.installOn(this);
-
- addKeyListener(new KeyAdapter() {
- @Override
- public void keyPressed(KeyEvent e) {
- if (isToggleEvent(e)) {
- TreePath treePath = tree.getLeadSelectionPath();
- if (treePath == null) return;
- final Object o = treePath.getLastPathComponent();
- if (!(o instanceof CheckedTreeNode)) return;
- CheckedTreeNode firstNode = (CheckedTreeNode)o;
- boolean checked = toggleNode(firstNode);
-
- TreePath[] selectionPaths = tree.getSelectionPaths();
- for (int i = 0; selectionPaths != null && i < selectionPaths.length; i++) {
- final TreePath selectionPath = selectionPaths[i];
- final Object o1 = selectionPath.getLastPathComponent();
- if (!(o1 instanceof CheckedTreeNode)) continue;
- CheckedTreeNode node = (CheckedTreeNode)o1;
- checkNode(node, checked);
- ((DefaultTreeModel)tree.getModel()).nodeChanged(node);
- }
-
- e.consume();
- }
- }
- });
-
- tree.setSelectionRow(0);
- }
-
- private static boolean isToggleEvent(KeyEvent e) {
- return e.getKeyCode() == KeyEvent.VK_SPACE;
- }
-
- protected boolean toggleNode(CheckedTreeNode node) {
- boolean checked = !node.isChecked();
- checkNode(node, checked);
-
- // notify model listeners about model change
- final TreeModel model = getTree().getModel();
- model.valueForPathChanged(new TreePath(node.getPath()), node.getUserObject());
-
- return checked;
- }
-
- private void checkNode(CheckedTreeNode node, boolean checked) {
- adjustParentsAndChildren(node, checked);
- repaint();
- }
-
- private void adjustParentsAndChildren(final CheckedTreeNode node, final boolean checked) {
- changeNodeState(node, checked);
- if (!checked) {
- TreeNode parent = node.getParent();
- while (parent != null) {
- if (parent instanceof CheckedTreeNode) {
- changeNodeState((CheckedTreeNode)parent, false);
- }
- parent = parent.getParent();
- }
- uncheckChildren(node);
- }
- else {
- checkChildren(node);
- }
- repaint();
- }
-
- private static void changeNodeState(final CheckedTreeNode node, final boolean checked) {
- if (node.isChecked() != checked) {
- node.setChecked(checked);
- }
- }
-
- private static void uncheckChildren(final CheckedTreeNode node) {
- final Enumeration children = node.children();
- while (children.hasMoreElements()) {
- final Object o = children.nextElement();
- if (!(o instanceof CheckedTreeNode)) continue;
- CheckedTreeNode child = (CheckedTreeNode)o;
- changeNodeState(child, false);
- uncheckChildren(child);
- }
- }
-
- private static void checkChildren(final CheckedTreeNode node) {
- final Enumeration children = node.children();
- while (children.hasMoreElements()) {
- final Object o = children.nextElement();
- if (!(o instanceof CheckedTreeNode)) continue;
- CheckedTreeNode child = (CheckedTreeNode)o;
- changeNodeState(child, true);
- checkChildren(child);
- }
- }
-
- @SuppressWarnings("unchecked")
- public <T> T[] getCheckedNodes(final Class<T> nodeType) {
- final ArrayList<T> nodes = new ArrayList<T>();
- final Object root = getTree().getModel().getRoot();
- if (!(root instanceof CheckedTreeNode)) {
- throw new IllegalStateException("The root must be instance of the " + CheckedTreeNode.class.getName() + ": " + root.getClass().getName());
- }
- new Object() {
- @SuppressWarnings("unchecked")
- public void collect(CheckedTreeNode node) {
- if (node.isLeaf()) {
- Object userObject = node.getUserObject();
- if (node.isChecked() && userObject != null && nodeType.isAssignableFrom(userObject.getClass())) {
- final T value = (T)userObject;
- nodes.add(value);
- }
- }
- else {
- for (int i = 0; i < node.getChildCount(); i++) {
- final TreeNode child = node.getChildAt(i);
- if (child instanceof CheckedTreeNode) {
- collect((CheckedTreeNode)child);
- }
- }
- }
- }
- }.collect((CheckedTreeNode)root);
- T[] result = (T[])Array.newInstance(nodeType, nodes.size());
- nodes.toArray(result);
- return result;
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
index ee44bdf2f08b..bf3d383aeebb 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
@@ -26,11 +26,13 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.*;
import com.intellij.ui.treeStructure.treetable.TreeColumnInfo;
import com.intellij.util.PlatformIcons;
+import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ComboBoxCellEditor;
import com.intellij.util.ui.tree.TreeUtil;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -38,12 +40,11 @@ import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
+import javax.swing.tree.TreePath;
import java.awt.*;
import java.io.File;
-import java.util.Arrays;
-import java.util.HashMap;
+import java.util.*;
import java.util.List;
-import java.util.Map;
/**
* This dialog allows selecting paths inside selected archives or directories.
@@ -108,17 +109,17 @@ public class DetectedRootsChooserDialog extends DialogWrapper {
private JScrollPane myPane;
private String myDescription;
- public DetectedRootsChooserDialog(Component component, List<SuggestedChildRootInfo> suggestedRoots) {
+ public DetectedRootsChooserDialog(Component component, Collection<SuggestedChildRootInfo> suggestedRoots) {
super(component, true);
init(suggestedRoots);
}
- public DetectedRootsChooserDialog(Project project, List<SuggestedChildRootInfo> suggestedRoots) {
+ public DetectedRootsChooserDialog(Project project, Collection<SuggestedChildRootInfo> suggestedRoots) {
super(project, true);
init(suggestedRoots);
}
- private void init(List<SuggestedChildRootInfo> suggestedRoots) {
+ private void init(Collection<SuggestedChildRootInfo> suggestedRoots) {
myDescription = XmlStringUtil.wrapInHtml(ApplicationNamesInfo.getInstance().getFullProductName() +
" just scanned files and detected the following " + StringUtil.pluralize("root", suggestedRoots.size()) + ".<br>" +
"Select items in the tree below or press Cancel to cancel operation.");
@@ -128,7 +129,7 @@ public class DetectedRootsChooserDialog extends DialogWrapper {
init();
}
- private static CheckboxTreeTable createTreeTable(List<SuggestedChildRootInfo> suggestedRoots) {
+ private static CheckboxTreeTable createTreeTable(Collection<SuggestedChildRootInfo> suggestedRoots) {
final CheckedTreeNode root = createRoot(suggestedRoots);
CheckboxTreeTable treeTable = new CheckboxTreeTable(root, new CheckboxTree.CheckboxTreeCellRenderer(true) {
@Override
@@ -189,14 +190,30 @@ public class DetectedRootsChooserDialog extends DialogWrapper {
column.setPreferredWidth(width);
column.setMaxWidth(width);
treeTable.setRootVisible(false);
+ new TreeTableSpeedSearch(treeTable, new Convertor<TreePath, String>() {
+ @Override
+ public String convert(TreePath o) {
+ Object node = o.getLastPathComponent();
+ if (!(node instanceof VirtualFileCheckedTreeNode)) return "";
+ return ((VirtualFileCheckedTreeNode)node).getFile().getPresentableUrl();
+ }
+ });
TreeUtil.expandAll(treeTable.getTree());
return treeTable;
}
- private static CheckedTreeNode createRoot(List<SuggestedChildRootInfo> suggestedRoots) {
+ private static CheckedTreeNode createRoot(Collection<SuggestedChildRootInfo> suggestedRoots) {
+ SuggestedChildRootInfo[] sortedRoots = suggestedRoots.toArray(new SuggestedChildRootInfo[suggestedRoots.size()]);
+ Arrays.sort(sortedRoots, new Comparator<SuggestedChildRootInfo>() {
+ @Override
+ public int compare(@NotNull SuggestedChildRootInfo o1, @NotNull SuggestedChildRootInfo o2) {
+ return o1.getDetectedRoot().getFile().getPresentableUrl().compareTo(o2.getDetectedRoot().getFile().getPresentableUrl());
+ }
+ });
+
CheckedTreeNode root = new CheckedTreeNode(null);
Map<VirtualFile, CheckedTreeNode> rootCandidateNodes = new HashMap<VirtualFile, CheckedTreeNode>();
- for (SuggestedChildRootInfo rootInfo : suggestedRoots) {
+ for (SuggestedChildRootInfo rootInfo : sortedRoots) {
final VirtualFile rootCandidate = rootInfo.getRootCandidate();
CheckedTreeNode parent = rootCandidateNodes.get(rootCandidate);
if (parent == null) {
@@ -230,6 +247,12 @@ public class DetectedRootsChooserDialog extends DialogWrapper {
return "DetectedRootsChooserDialog";
}
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return myTreeTable;
+ }
+
private static class VirtualFileCheckedTreeNode extends CheckedTreeNode {
private final VirtualFile myFile;
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java
index 743e408b8c97..725216600ffa 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/SuggestedChildRootInfo.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.roots.libraries.LibraryRootType;
import com.intellij.openapi.roots.libraries.ui.DetectedLibraryRoot;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Map;
@@ -32,17 +33,19 @@ class SuggestedChildRootInfo {
private final Map<LibraryRootType, String> myRootTypeNames;
private LibraryRootType mySelectedRootType;
- SuggestedChildRootInfo(VirtualFile rootCandidate, DetectedLibraryRoot detectedRoot, Map<LibraryRootType, String> rootTypeNames) {
+ SuggestedChildRootInfo(@NotNull VirtualFile rootCandidate, @NotNull DetectedLibraryRoot detectedRoot, @NotNull Map<LibraryRootType, String> rootTypeNames) {
myRootCandidate = rootCandidate;
myDetectedRoot = detectedRoot;
myRootTypeNames = rootTypeNames;
mySelectedRootType = detectedRoot.getTypes().get(0);
}
+ @NotNull
public VirtualFile getRootCandidate() {
return myRootCandidate;
}
+ @NotNull
public DetectedLibraryRoot getDetectedRoot() {
return myDetectedRoot;
}
@@ -51,6 +54,7 @@ class SuggestedChildRootInfo {
return myRootTypeNames.get(type);
}
+ @NotNull
public LibraryRootType getSelectedRootType() {
return mySelectedRootType;
}
@@ -64,6 +68,7 @@ class SuggestedChildRootInfo {
}
}
+ @NotNull
public String[] getRootTypeNames() {
final String[] types = ArrayUtil.toStringArray(myRootTypeNames.values());
Arrays.sort(types, String.CASE_INSENSITIVE_ORDER);
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
index 72f9c5a965c0..04f908a17c00 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.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.
@@ -33,12 +33,15 @@ import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.ui.componentsList.components.ScrollablePanel;
import com.intellij.openapi.roots.ui.componentsList.layout.VerticalStackLayout;
import com.intellij.openapi.roots.ui.configuration.actions.IconWithTextAction;
-import com.intellij.openapi.ui.Splitter;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.ex.VirtualFileManagerAdapter;
+import com.intellij.ui.JBSplitter;
+import com.intellij.ui.OnePixelSplitter;
import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.roots.ToolbarPanel;
import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
@@ -48,6 +51,7 @@ import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import javax.swing.*;
import javax.swing.border.Border;
+import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
@@ -146,7 +150,9 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor {
myContentEntryEditorListener = new MyContentEntryEditorListener();
final JPanel mainPanel = new JPanel(new BorderLayout());
- mainPanel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
+ if (!Registry.is("ide.new.project.settings")) {
+ mainPanel.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6));
+ }
addAdditionalSettingsToPanel(mainPanel);
@@ -159,21 +165,32 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor {
myEditorsPanel = new ScrollablePanel(new VerticalStackLayout());
myEditorsPanel.setBackground(BACKGROUND_COLOR);
- JScrollPane myScrollPane = ScrollPaneFactory.createScrollPane(myEditorsPanel);
- entriesPanel.add(new ToolbarPanel(myScrollPane, group), BorderLayout.CENTER);
+ JScrollPane myScrollPane = ScrollPaneFactory.createScrollPane(myEditorsPanel, Registry.is("ide.new.project.settings"));
+ final ToolbarPanel toolbarPanel = new ToolbarPanel(myScrollPane, group);
+ if (Registry.is("ide.new.project.settings")) {
+ toolbarPanel.setBorder(new CustomLineBorder(1,0,0,0));
+ }
+ entriesPanel.add(toolbarPanel, BorderLayout.CENTER);
- final Splitter splitter = new Splitter(false);
+ final JBSplitter splitter = Registry.is("ide.new.project.settings") ? new OnePixelSplitter(false) : new JBSplitter(false);
splitter.setProportion(0.6f);
splitter.setHonorComponentsMinimumSize(true);
myRootTreeEditor = createContentEntryTreeEditor(project);
- splitter.setFirstComponent(myRootTreeEditor.createComponent());
+ final JComponent component = myRootTreeEditor.createComponent();
+ if (Registry.is("ide.new.project.settings")) {
+ component.setBorder(new CustomLineBorder(1,0,0,0));
+ }
+
+ splitter.setFirstComponent(component);
splitter.setSecondComponent(entriesPanel);
JPanel contentPanel = new JPanel(new GridBagLayout());
- contentPanel.setBorder(BorderFactory.createEtchedBorder());
+ if (!Registry.is("ide.new.project.settings")) {
+ contentPanel.setBorder(BorderFactory.createEtchedBorder());
+ }
final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, myRootTreeEditor.getEditingActionsGroup(), true);
contentPanel.add(new JLabel("Mark as:"),
- new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(0, 5, 0, 5), 0, 0));
+ new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.WEST, 0, new Insets(0, 10, 0, 10), 0, 0));
contentPanel.add(actionToolbar.getComponent(),
new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
new Insets(0, 0, 0, 0), 0, 0));
@@ -236,7 +253,11 @@ public class CommonContentEntriesEditor extends ModuleElementsEditor {
if (componentBorder != null) {
border = BorderFactory.createCompoundBorder(border, componentBorder);
}
- component.setBorder(border);
+ if (Registry.is("ide.new.project.settings")) {
+ component.setBorder(new EmptyBorder(0,0,0,0));
+ } else {
+ component.setBorder(border);
+ }
myEditorsPanel.add(component);
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java
index 469d966a29d8..bc10302c9c43 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentRootPanel.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.
@@ -36,6 +36,7 @@ import com.intellij.ui.roots.IconActionComponent;
import com.intellij.ui.roots.ResizingWrapper;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
+import com.intellij.util.NotNullProducer;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -59,10 +60,22 @@ import java.util.Map;
*/
public abstract class ContentRootPanel extends JPanel {
private static final Color EXCLUDED_COLOR = new JBColor(new Color(0x992E00), DarculaColors.RED);
- private static final Color SELECTED_HEADER_COLOR = new JBColor(new Color(0xDEF2FF), UIUtil.getPanelBackground().darker());
+ private static final Color SELECTED_HEADER_COLOR = new JBColor(new NotNullProducer<Color>() {
+ @NotNull
+ @Override
+ public Color produce() {
+ return UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground().darker() : new Color(0xDEF2FF);
+ }
+ });
private static final Color HEADER_COLOR = new JBColor(new Color(0xF5F5F5), Gray._82);
private static final Color SELECTED_CONTENT_COLOR = new Color(0xF0F9FF);
- private static final Color CONTENT_COLOR = new JBColor(Color.WHITE, UIUtil.getPanelBackground());
+ private static final Color CONTENT_COLOR = new JBColor(new NotNullProducer<Color>() {
+ @NotNull
+ @Override
+ public Color produce() {
+ return UIUtil.isUnderDarcula() ? UIUtil.getPanelBackground() : Gray._255;
+ }
+ });
private static final Color UNSELECTED_TEXT_COLOR = Gray._51;
protected final ActionCallback myCallback;
@@ -140,7 +153,7 @@ public abstract class ContentRootPanel extends JPanel {
headerLabel.setFont(headerLabel.getFont().deriveFont(Font.BOLD));
headerLabel.setOpaque(false);
if (getContentEntry().getFile() == null) {
- headerLabel.setForeground(Color.RED);
+ headerLabel.setForeground(JBColor.RED);
}
final IconActionComponent deleteIconComponent = new IconActionComponent(AllIcons.Modules.DeleteContentRoot,
AllIcons.Modules.DeleteContentRootRollover,
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java
deleted file mode 100644
index d92445254f28..000000000000
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AddScopeUtil.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * User: anna
- * Date: 14-May-2009
- */
-package com.intellij.profile.codeInspection.ui;
-
-import com.intellij.codeHighlighting.HighlightDisplayLevel;
-import com.intellij.codeInspection.ex.Descriptor;
-import com.intellij.codeInspection.ex.InspectionProfileImpl;
-import com.intellij.codeInspection.ex.InspectionToolWrapper;
-import com.intellij.codeInspection.ex.ScopeToolState;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionConfigTreeNode;
-import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx;
-import com.intellij.psi.search.scope.packageSet.NamedScope;
-import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
-import com.intellij.ui.treeStructure.Tree;
-import com.intellij.ui.treeStructure.treetable.TreeTable;
-import com.intellij.util.ArrayUtil;
-
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.TreePath;
-import java.util.*;
-
-public class AddScopeUtil {
- public static ScopeToolState performAddScope(final TreeTable treeTable,
- final Project project,
- final InspectionProfileImpl inspectionProfile,
- final Collection<InspectionConfigTreeNode> selectedNodes) {
- final List<InspectionConfigTreeNode> nodes = new ArrayList<InspectionConfigTreeNode>();
- final List<Descriptor> descriptors = new ArrayList<Descriptor>();
- for (final InspectionConfigTreeNode node : selectedNodes) {
- collect(descriptors, nodes, node);
- }
-
- final List<String> availableScopes = getAvailableScopes(descriptors, project, inspectionProfile);
- final int idx = Messages.showChooseDialog(treeTable, "Scope:", "Choose Scope", ArrayUtil.toStringArray(availableScopes), availableScopes.get(0), Messages.getQuestionIcon());
- if (idx == -1) return null;
- final NamedScope chosenScope = NamedScopesHolder.getScope(project, availableScopes.get(idx));
-
- ScopeToolState scopeToolState = null;
- final Tree tree = treeTable.getTree();
-
- for (final InspectionConfigTreeNode node : nodes) {
- final Descriptor descriptor = node.getDefaultDescriptor();
- final InspectionToolWrapper toolWrapper = descriptor.getToolWrapper().createCopy(); //copy
- final HighlightDisplayLevel level = inspectionProfile.getErrorLevel(descriptor.getKey(), chosenScope, project);
- final boolean enabled = inspectionProfile.isToolEnabled(descriptor.getKey());
- scopeToolState = inspectionProfile.addScope(toolWrapper, chosenScope, level, enabled, project);
- node.dropCache();
- ((DefaultTreeModel)tree.getModel()).reload(node);
- tree.expandPath(new TreePath(node.getPath()));
- }
- tree.revalidate();
- return scopeToolState;
- }
-
- private static void collect(final List<Descriptor> descriptors,
- final List<InspectionConfigTreeNode> nodes,
- final InspectionConfigTreeNode node) {
- final ToolDescriptors currentDescriptors = node.getDescriptors();
- if (currentDescriptors != null) {
- nodes.add(node);
- descriptors.add(currentDescriptors.getDefaultDescriptor());
- descriptors.addAll(currentDescriptors.getNonDefaultDescriptors());
- } else if (node.getUserObject() instanceof String) {
- for(int i = 0; i < node.getChildCount(); i++) {
- final InspectionConfigTreeNode childNode = (InspectionConfigTreeNode)node.getChildAt(i);
- collect(descriptors, nodes, childNode);
- }
- }
- }
-
- private static List<String> getAvailableScopes(final List<Descriptor> descriptors, final Project project, final InspectionProfileImpl inspectionProfile) {
- final ArrayList<NamedScope> scopes = new ArrayList<NamedScope>();
- for (final NamedScopesHolder holder : NamedScopesHolder.getAllNamedScopeHolders(project)) {
- Collections.addAll(scopes, holder.getScopes());
- }
- scopes.remove(CustomScopesProviderEx.getAllScope());
-
- CustomScopesProviderEx.filterNoSettingsScopes(project, scopes);
-
- final Set<NamedScope> used = new HashSet<NamedScope>();
- for (final Descriptor descriptor : descriptors) {
- final List<ScopeToolState> nonDefaultTools = inspectionProfile.getNonDefaultTools(descriptor.getKey().toString(), project);
- if (nonDefaultTools != null) {
- for (final ScopeToolState state : nonDefaultTools) {
- used.add(state.getScope(project));
- }
- }
- }
- scopes.removeAll(used);
-
- final List<String> availableScopes = new ArrayList<String>();
- for (final NamedScope scope : scopes) {
- availableScopes.add(scope.getName());
- }
- return availableScopes;
- }
-} \ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java
new file mode 100644
index 000000000000..b0746769d83c
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/AdvancedSettingsAction.java
@@ -0,0 +1,209 @@
+/*
+ * 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.profile.codeInspection.ui;
+
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.ui.popup.PopupStep;
+import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
+import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionConfigTreeNode;
+import com.intellij.ui.LayeredIcon;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.ui.popup.list.ListPopupImpl;
+import com.intellij.util.Consumer;
+import com.intellij.util.PlatformIcons;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.EmptyIcon;
+import com.intellij.util.ui.UIUtil;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public abstract class AdvancedSettingsAction extends AnAction {
+ private final int myCheckBoxIndent;
+ private Project myProject;
+ private InspectionConfigTreeNode myRoot;
+
+ public AdvancedSettingsAction(final Project project, InspectionConfigTreeNode root) {
+ super("Advanced Settings");
+ getTemplatePresentation().setIcon(AllIcons.General.Gear);
+ myProject = project;
+ myRoot = root;
+ myCheckBoxIndent = calculateCheckBoxIndent();
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ super.update(e);
+ final InspectionProfileImpl inspectionProfile = getInspectionProfile();
+ final Icon icon = AllIcons.General.Gear;
+ e.getPresentation().setIcon(
+ (inspectionProfile != null && inspectionProfile.isProfileLocked()) ? LayeredIcon.create(icon, PlatformIcons.LOCKED_ICON) : icon);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ final ListPopupImpl actionGroupPopup = (ListPopupImpl)JBPopupFactory.getInstance().createListPopup(
+ new BaseListPopupStep<MyAction>(null, ContainerUtil.list(new MyDisableNewInspectionsAction(), new MyResetAction())) {
+ @Override
+ public PopupStep onChosen(MyAction selectedValue, boolean finalChoice) {
+ if (selectedValue.enabled()) {
+ selectedValue.actionPerformed();
+ }
+ return FINAL_CHOICE;
+ }
+ });
+ actionGroupPopup.getList().setCellRenderer(new ListCellRenderer() {
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ return ((MyAction)value).createCustomComponent(isSelected);
+ }
+ });
+ final Component component = e.getInputEvent().getComponent();
+ actionGroupPopup.show(new RelativePoint(component, new Point(component.getWidth() - 1, 0)));
+ }
+
+ private JLabel installLeftIndentToLabel(final JLabel label) {
+ label.setBorder(BorderFactory.createEmptyBorder(0, myCheckBoxIndent, 0, 0));
+ return label;
+ }
+
+ private class MyResetAction extends MyAction {
+
+ protected MyResetAction() {
+ super("All your changes will be lost");
+ }
+
+ @Override
+ protected JComponent createBaseComponent() {
+ return installLeftIndentToLabel(new JLabel("Reset to Defaults Settings"));
+ }
+
+ @Override
+ public void actionPerformed() {
+ final InspectionProfileImpl inspectionProfile = getInspectionProfile();
+ if (inspectionProfile == null) {
+ return;
+ }
+ inspectionProfile.resetToBase(myProject);
+ postProcessModification();
+ }
+
+ @Override
+ protected boolean enabled() {
+ return myRoot.isProperSetting();
+ }
+ }
+
+ private class MyDisableNewInspectionsAction extends MyAction {
+ public MyDisableNewInspectionsAction() {
+ super("New inspections may appear when " + ApplicationNamesInfo.getInstance().getFullProductName() + " is updated");
+ }
+
+ @Override
+ protected JComponent createBaseComponent() {
+ final JCheckBox checkBox = new JCheckBox("Disable new inspections by default");
+ final InspectionProfileImpl profile = getInspectionProfile();
+ checkBox.setEnabled(profile != null);
+ if (profile != null) {
+ checkBox.setSelected(profile.isProfileLocked());
+ }
+ checkBox.setOpaque(false);
+ return checkBox;
+ }
+
+ @Override
+ public void actionPerformed() {
+ final InspectionProfileImpl profile = getInspectionProfile();
+ if (profile != null) {
+ profile.lockProfile(!profile.isProfileLocked());
+ }
+ }
+
+
+ @Override
+ protected boolean enabled() {
+ return true;
+ }
+ }
+
+ private abstract class MyAction {
+ private final String myDescription;
+
+ protected MyAction(String description) {
+ myDescription = description;
+ }
+
+ protected abstract JComponent createBaseComponent();
+
+ protected abstract void actionPerformed();
+
+ protected abstract boolean enabled();
+
+ public JComponent createCustomComponent(final boolean selected) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
+ panel.add(createBaseComponent());
+ panel.add(installLeftIndentToLabel(new JBLabel(myDescription, UIUtil.ComponentStyle.MINI)));
+ panel.setBackground(selected ? UIUtil.getListSelectionBackground() : UIUtil.getListBackground());
+ panel.setForeground(selected ? UIUtil.getListSelectionForeground() : UIUtil.getListForeground());
+ UIUtil.setEnabled(panel, enabled(), true);
+ return panel;
+ }
+ }
+
+ protected abstract InspectionProfileImpl getInspectionProfile();
+
+ protected abstract void postProcessModification();
+
+ private static int calculateCheckBoxIndent() {
+ JCheckBox checkBox = new JCheckBox();
+ Icon icon = checkBox.getIcon();
+ int indent = 0;
+ if (icon == null) {
+ icon = UIManager.getIcon("CheckBox.icon");
+ }
+ if (UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) {
+ icon = EmptyIcon.create(20, 18);
+ }
+ if (icon != null) {
+ final Insets i = checkBox.getInsets();
+ final Rectangle r = checkBox.getBounds();
+ final Rectangle r1 = new Rectangle();
+ r1.x = i.left;
+ r1.y = i.top;
+ r1.width = r.width - (i.right + r1.x);
+ r1.height = r.height - (i.bottom + r1.y);
+ final Rectangle iconRect = new Rectangle();
+ SwingUtilities.layoutCompoundLabel(
+ checkBox, checkBox.getFontMetrics(checkBox.getFont()), checkBox.getText(), icon,
+ checkBox.getVerticalAlignment(), checkBox.getHorizontalAlignment(),
+ checkBox.getVerticalTextPosition(), checkBox.getHorizontalTextPosition(),
+ r1, new Rectangle(), iconRect,
+ checkBox.getText() == null ? 0 : checkBox.getIconTextGap());
+ indent = iconRect.x;
+ }
+ return indent + checkBox.getIconTextGap();
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java
index 794945268d19..efc60c63f89d 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionToolsConfigurable.java
@@ -151,7 +151,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple
final Set<String> levels = new HashSet<String>();
for (Object o : rootElement.getChildren("inspection_tool")) {
final Element inspectElement = (Element)o;
- levels.add(inspectElement.getAttributeValue("l"));
+ levels.add(inspectElement.getAttributeValue("level"));
for (Object s : inspectElement.getChildren("scope")) {
levels.add(((Element)s).getAttributeValue("level"));
}
@@ -532,6 +532,6 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable imple
public JComponent getPreferredFocusedComponent() {
final InspectionProfileImpl inspectionProfile = getSelectedObject();
assert inspectionProfile != null : configuredProfiles();
- return getProfilePanel(inspectionProfile).getTree();
+ return getProfilePanel(inspectionProfile).getPreferredFocusedComponent();
}
}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java
index 1067a60ed358..df3b8bda3f3b 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java
@@ -43,7 +43,11 @@ public abstract class LevelChooserAction extends ComboBoxAction {
private HighlightSeverity myChosen = null;
public LevelChooserAction(final InspectionProfileImpl profile) {
- mySeverityRegistrar = ((SeverityProvider)profile.getProfileManager()).getOwnSeverityRegistrar();
+ this(((SeverityProvider)profile.getProfileManager()).getOwnSeverityRegistrar());
+ }
+
+ public LevelChooserAction(final SeverityRegistrar severityRegistrar) {
+ mySeverityRegistrar = severityRegistrar;
}
@NotNull
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java
deleted file mode 100644
index 2bf909666f82..000000000000
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/MultiScopeSeverityIcon.java
+++ /dev/null
@@ -1,58 +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 com.intellij.profile.codeInspection.ui;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.List;
-
-/**
- * @author Dmitry Batkovich
- */
-public class MultiScopeSeverityIcon implements Icon {
- private final int mySize;
- private final List<Color> myColors;
-
- public MultiScopeSeverityIcon(final int size, final List<Color> colors) {
- mySize = size;
- myColors = colors;
- }
-
- @Override
- public void paintIcon(final Component c, final Graphics g, final int i, final int j) {
- final int iconWidth = getIconWidth();
- final int iconHeightCoordinate = j + getIconHeight();
-
- final int partWidth = iconWidth / myColors.size();
-
- for (int idx = 0; idx < myColors.size(); idx++) {
- final Color color = myColors.get(idx);
- g.setColor(color);
- final int x = i + partWidth * idx;
- g.fillRect(x, j, x + partWidth, iconHeightCoordinate);
- }
- }
-
- @Override
- public int getIconWidth() {
- return mySize;
- }
-
- @Override
- public int getIconHeight() {
- return mySize;
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java
new file mode 100644
index 000000000000..f2d8c5e1fd82
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopeOrderComparator.java
@@ -0,0 +1,62 @@
+/*
+ * 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.profile.codeInspection.ui;
+
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.util.ArrayUtil;
+
+import java.util.Comparator;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ScopeOrderComparator implements Comparator<String> {
+ private final String[] myScopesOrder;
+
+ public ScopeOrderComparator(final InspectionProfileImpl inspectionProfile) {
+ this(inspectionProfile.getScopesOrder());
+ }
+
+ public ScopeOrderComparator(String[] scopesOrder) {
+ myScopesOrder = scopesOrder;
+ }
+
+ private int getKey(String scope) {
+ return myScopesOrder == null ? -1 : ArrayUtil.indexOf(myScopesOrder, scope);
+ }
+
+ @Override
+ public int compare(String scope1, String scope2) {
+ final int key = getKey(scope1);
+ final int key1 = getKey(scope2);
+ if (key >= 0) {
+ if (key1 >= 0) {
+ return key - key1;
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ if (key1 >= 0) {
+ return 1;
+ }
+ else {
+ return scope1.compareTo(scope2);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java
index 4932e7ff5ca9..fde3b141084d 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesChooser.java
@@ -22,13 +22,16 @@ import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.project.Project;
+import com.intellij.psi.search.scope.NonProjectFilesScope;
import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.ArrayList;
+import java.util.Set;
import java.util.List;
import java.util.Collections;
@@ -36,22 +39,28 @@ import java.util.Collections;
* @author Dmitry Batkovich
*/
public abstract class ScopesChooser extends ComboBoxAction {
+ public static final String TITLE = "Select a scope to change its settings";
private final List<Descriptor> myDefaultDescriptors;
private final InspectionProfileImpl myInspectionProfile;
private final Project myProject;
+ private final Set<String> myExcludedScopeNames;
- public ScopesChooser(final List<Descriptor> defaultDescriptors, final InspectionProfileImpl inspectionProfile, final Project project) {
+ public ScopesChooser(final List<Descriptor> defaultDescriptors,
+ final InspectionProfileImpl inspectionProfile,
+ final Project project,
+ final String[] excludedScopeNames) {
myDefaultDescriptors = defaultDescriptors;
myInspectionProfile = inspectionProfile;
myProject = project;
- setPopupTitle("Select a scope to change its settings");
+ myExcludedScopeNames = excludedScopeNames == null ? Collections.<String>emptySet() : ContainerUtil.newHashSet(excludedScopeNames);
+ setPopupTitle(TITLE);
getTemplatePresentation().setText("In All Scopes");
}
@NotNull
@Override
- protected DefaultActionGroup createPopupActionGroup(final JComponent button) {
+ public DefaultActionGroup createPopupActionGroup(final JComponent component) {
final DefaultActionGroup group = new DefaultActionGroup();
final List<NamedScope> predefinedScopes = new ArrayList<NamedScope>();
@@ -61,30 +70,47 @@ public abstract class ScopesChooser extends ComboBoxAction {
predefinedScopes.addAll(holder.getPredefinedScopes());
}
predefinedScopes.remove(CustomScopesProviderEx.getAllScope());
- fillActionGroup(group, predefinedScopes, myDefaultDescriptors, myInspectionProfile);
+ for (NamedScope predefinedScope : predefinedScopes) {
+ if (predefinedScope instanceof NonProjectFilesScope) {
+ predefinedScopes.remove(predefinedScope);
+ break;
+ }
+ }
+
+ fillActionGroup(group, predefinedScopes, myDefaultDescriptors, myInspectionProfile, myExcludedScopeNames);
group.addSeparator();
- fillActionGroup(group, customScopes, myDefaultDescriptors, myInspectionProfile);
+ fillActionGroup(group, customScopes, myDefaultDescriptors, myInspectionProfile, myExcludedScopeNames);
- //TODO edit scopes order
- //group.addSeparator();
- //group.add(new AnAction("Edit Scopes Order...") {
- // @Override
- // public void actionPerformed(final AnActionEvent e) {
- //
- // }
- //});
+ group.addSeparator();
+ group.add(new AnAction("Edit Scopes Order...") {
+ @Override
+ public void actionPerformed(final AnActionEvent e) {
+ final ScopesOrderDialog dlg = new ScopesOrderDialog(component, myInspectionProfile, myProject);
+ dlg.show();
+ if (dlg.isOK()) {
+ onScopesOrderChanged();
+ }
+ }
+ });
return group;
}
+ protected abstract void onScopesOrderChanged();
+
protected abstract void onScopeAdded();
private void fillActionGroup(final DefaultActionGroup group,
- final List<NamedScope> scopes,
- final List<Descriptor> defaultDescriptors,
- final InspectionProfileImpl inspectionProfile) {
+ final List<NamedScope> scopes,
+ final List<Descriptor> defaultDescriptors,
+ final InspectionProfileImpl inspectionProfile,
+ final Set<String> excludedScopeNames) {
for (final NamedScope scope : scopes) {
- group.add(new AnAction(scope.getName()) {
+ final String scopeName = scope.getName();
+ if (excludedScopeNames.contains(scopeName)) {
+ continue;
+ }
+ group.add(new AnAction(scopeName) {
@Override
public void actionPerformed(final AnActionEvent e) {
for (final Descriptor defaultDescriptor : defaultDescriptors) {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java
new file mode 100644
index 000000000000..c69a3e5566a2
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ScopesOrderDialog.java
@@ -0,0 +1,121 @@
+/*
+ * 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.profile.codeInspection.ui;
+
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.psi.search.scope.NonProjectFilesScope;
+import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx;
+import com.intellij.psi.search.scope.packageSet.NamedScope;
+import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
+import com.intellij.ui.*;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ScopesOrderDialog extends DialogWrapper {
+
+ private final JList myOptionsList = new JBList();
+
+ private final InspectionProfileImpl myInspectionProfile;
+ private final Project myProject;
+ private final JPanel myPanel;
+
+ public ScopesOrderDialog(final @NotNull Component parent,
+ final InspectionProfileImpl inspectionProfile,
+ final Project project) {
+ super(parent, true);
+ myInspectionProfile = inspectionProfile;
+ myProject = project;
+
+ final JPanel listPanel = ToolbarDecorator.createDecorator(myOptionsList).setMoveDownAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton anActionButton) {
+ ListUtil.moveSelectedItemsDown(myOptionsList);
+ }
+ }).setMoveUpAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton anActionButton) {
+ ListUtil.moveSelectedItemsUp(myOptionsList);
+ }
+ }).disableRemoveAction().disableAddAction().createPanel();
+ final JLabel descr = new JLabel("<html><p>If file appears in two or more scopes, it will be" +
+ "inspected with settings of the topmost scope in list above.</p><p/>" +
+ "<p>Scope order is set globally for all inspections in the profile.</p></html>");
+ descr.setPreferredSize(new Dimension(300, 100));
+ UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, descr);
+ myPanel = new JPanel();
+ myPanel.setLayout(new BorderLayout());
+ myPanel.add(listPanel, BorderLayout.CENTER);
+ myPanel.add(descr, BorderLayout.SOUTH);
+ fillList();
+ init();
+ setTitle("Scopes Order");
+ }
+
+ private void fillList() {
+ DefaultListModel model = new DefaultListModel();
+ model.removeAllElements();
+
+ final List<String> scopes = new ArrayList<String>();
+ for (final NamedScopesHolder holder : NamedScopesHolder.getAllNamedScopeHolders(myProject)) {
+ for (final NamedScope scope : holder.getScopes()) {
+ if (!(scope instanceof NonProjectFilesScope)) {
+ scopes.add(scope.getName());
+ }
+ }
+ }
+ scopes.remove(CustomScopesProviderEx.getAllScope().getName());
+ Collections.sort(scopes, new ScopeOrderComparator(myInspectionProfile));
+ for (String scopeName : scopes) {
+ model.addElement(scopeName);
+ }
+ myOptionsList.setModel(model);
+ myOptionsList.setSelectedIndex(0);
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ return myPanel;
+ }
+
+ @Override
+ protected void doOKAction() {
+ final int size = myOptionsList.getModel().getSize();
+ final String[] newScopeOrder = new String[size];
+ for (int i = 0; i < size; i++) {
+ final String scopeName = (String) myOptionsList.getModel().getElementAt(i);
+ newScopeOrder[i] = scopeName;
+ }
+ if (!Arrays.equals(newScopeOrder, myInspectionProfile.getScopesOrder())) {
+ myInspectionProfile.setScopesOrder(newScopeOrder);
+ }
+ super.doOKAction();
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
index ce5f308c1305..2da5c80a758b 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
@@ -132,6 +132,8 @@ public class SingleInspectionProfilePanel extends JPanel {
private Splitter myRightSplitter;
private Splitter myMainSplitter;
+ private String[] myInitialScopesOrder;
+
public SingleInspectionProfilePanel(@NotNull InspectionProjectProfileManager projectProfileManager,
@NotNull String inspectionProfileName,
@NotNull ModifiableModel profile) {
@@ -186,8 +188,10 @@ public class SingleInspectionProfilePanel extends JPanel {
if (myTreeTable != null) {
final TreePath selectionPath = myTreeTable.getTree().getSelectionPath();
if (selectionPath != null) {
- TreeUtil.selectNode(myTreeTable.getTree(), (TreeNode)selectionPath.getLastPathComponent());
- TreeUtil.showRowCentered(myTreeTable.getTree(), myTreeTable.getTree().getRowForPath(selectionPath), false);
+ TreeUtil.selectNode(myTreeTable.getTree(), (TreeNode) selectionPath.getLastPathComponent());
+ final int rowForPath = myTreeTable.getTree().getRowForPath(selectionPath);
+ TableUtil.selectRows(myTreeTable, new int[]{rowForPath});
+ scrollToCenter();
}
}
}
@@ -258,6 +262,7 @@ public class SingleInspectionProfilePanel extends JPanel {
if (!accept(state.getTool())) continue;
myInitialToolDescriptors.add(ToolDescriptors.fromScopeToolState(state, profile, project));
}
+ myInitialScopesOrder = mySelectedProfile.getScopesOrder();
}
protected boolean accept(InspectionToolWrapper entry) {
@@ -364,24 +369,6 @@ public class SingleInspectionProfilePanel extends JPanel {
actions.add(actionManager.createExpandAllAction(myTreeExpander, myTreeTable));
actions.add(actionManager.createCollapseAllAction(myTreeExpander, myTreeTable));
-
- actions.add(new AnAction(CommonBundle.message("button.reset.to.default"), CommonBundle.message("button.reset.to.default"),
- AllIcons.General.Reset) {
- {
- registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK)), myTreeTable);
- }
- @Override
- public void update(AnActionEvent e) {
- e.getPresentation().setEnabled(myRoot.isProperSetting());
- }
-
- @Override
- public void actionPerformed(AnActionEvent e) {
- mySelectedProfile.resetToBase(myProjectProfileManager.getProject());
- postProcessModification();
- }
- });
-
actions.add(new AnAction("Reset to Empty", "Reset to empty", AllIcons.Actions.Reset_to_empty){
@Override
@@ -396,18 +383,19 @@ public class SingleInspectionProfilePanel extends JPanel {
}
});
- actions.add(new ToggleAction("Lock Profile", "Lock profile", AllIcons.Nodes.Padlock) {
+ actions.add(new AdvancedSettingsAction(myProjectProfileManager.getProject(), myRoot) {
@Override
- public boolean isSelected(AnActionEvent e) {
- return mySelectedProfile != null && mySelectedProfile.isProfileLocked();
+ protected InspectionProfileImpl getInspectionProfile() {
+ return mySelectedProfile;
}
@Override
- public void setSelected(AnActionEvent e, boolean state) {
- mySelectedProfile.lockProfile(state);
+ protected void postProcessModification() {
+ SingleInspectionProfilePanel.this.postProcessModification();
}
});
+
final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, actions, true);
actionToolbar.setTargetComponent(this);
return actionToolbar;
@@ -424,11 +412,24 @@ public class SingleInspectionProfilePanel extends JPanel {
public void selectInspectionTool(String name) {
final InspectionConfigTreeNode node = findNodeByKey(name, myRoot);
if (node != null) {
- TreeUtil.showRowCentered(myTreeTable.getTree(), myTreeTable.getTree().getRowForPath(new TreePath(node.getPath())) - 1, true);//myTree.isRootVisible ? 0 : 1;
TreeUtil.selectNode(myTreeTable.getTree(), node);
+ final int rowForPath = myTreeTable.getTree().getRowForPath(new TreePath(node.getPath()));
+ TableUtil.selectRows(myTreeTable, new int[]{rowForPath});
+ scrollToCenter();
}
}
+ private void scrollToCenter() {
+ ListSelectionModel selectionModel = myTreeTable.getSelectionModel();
+ int maxSelectionIndex = selectionModel.getMaxSelectionIndex();
+ final int maxColumnSelectionIndex = Math.max(0, myTreeTable.getColumnModel().getSelectionModel().getMinSelectionIndex());
+ Rectangle maxCellRect = myTreeTable.getCellRect(maxSelectionIndex, maxColumnSelectionIndex, false);
+
+ final Point selectPoint = maxCellRect.getLocation();
+ final int allHeight = myTreeTable.getVisibleRect().height;
+ myTreeTable.scrollRectToVisible(new Rectangle(new Point(0, Math.max(0, selectPoint.y - allHeight / 2)), new Dimension(0, allHeight)));
+ }
+
@Nullable
private static InspectionConfigTreeNode findNodeByKey(String name, InspectionConfigTreeNode root) {
for (int i = 0; i < root.getChildCount(); i++) {
@@ -524,6 +525,7 @@ public class SingleInspectionProfilePanel extends JPanel {
final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTreeTable);
+ myTreeTable.getTree().setShowsRootHandles(true);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
TreeUtil.collapseAll(myTreeTable.getTree(), 1);
@@ -684,14 +686,15 @@ public class SingleInspectionProfilePanel extends JPanel {
}
private void updateOptionsAndDescriptionPanel(final TreePath... paths) {
- if (paths == null || paths.length == 0) {
+ if (mySelectedProfile == null || paths == null || paths.length == 0) {
return;
}
final TreePath path = paths[0];
if (path == null) return;
final List<InspectionConfigTreeNode> nodes = InspectionsAggregationUtil.getInspectionsNodes(paths);
if (!nodes.isEmpty()) {
- final InspectionConfigTreeNode singleNode = nodes.size() == 1 ? ContainerUtil.getFirstItem(nodes) : null;
+ final InspectionConfigTreeNode singleNode = paths.length == 1 && ((InspectionConfigTreeNode)paths[0].getLastPathComponent()).getDefaultDescriptor() != null
+ ? ContainerUtil.getFirstItem(nodes) : null;
if (singleNode != null && singleNode.getDefaultDescriptor().loadDescription() != null) {
// need this in order to correctly load plugin-supplied descriptions
final Descriptor defaultDescriptor = singleNode.getDefaultDescriptor();
@@ -721,7 +724,7 @@ public class SingleInspectionProfilePanel extends JPanel {
}
else {
try {
- myBrowser.read(new StringReader(EMPTY_HTML), null);
+ myBrowser.read(new StringReader("<html><body>Multiple inspections are selected. You can edit them as a single inspection.</body></html>"), null);
}
catch (IOException e1) {
//Can't be
@@ -733,7 +736,6 @@ public class SingleInspectionProfilePanel extends JPanel {
final JPanel severityPanel = new JPanel(new GridBagLayout());
final double severityPanelWeightY;
final JPanel configPanelAnchor = new JPanel(new GridLayout());
- configPanelAnchor.setBorder(IdeBorderFactory.createTitledBorder("Options", false, new Insets(0, 0, 0, 0)));
final Set<String> scopesNames = new THashSet<String>();
for (final InspectionConfigTreeNode node : nodes) {
@@ -754,7 +756,7 @@ public class SingleInspectionProfilePanel extends JPanel {
final HighlightDisplayKey key = node.getDefaultDescriptor().getKey();
final NamedScope scope = node.getDefaultDescriptor().getScope();
final boolean toUpdate = mySelectedProfile.getErrorLevel(key, scope, project) != level;
- mySelectedProfile.setErrorLevel(key, level, -1, project);
+ mySelectedProfile.setErrorLevel(key, level, null, project);
if (toUpdate) node.dropCache();
}
@@ -774,7 +776,13 @@ public class SingleInspectionProfilePanel extends JPanel {
public Descriptor fun(final InspectionConfigTreeNode node) {
return node.getDefaultDescriptor();
}
- }), mySelectedProfile, project) {
+ }), mySelectedProfile, project, null) {
+ @Override
+ protected void onScopesOrderChanged() {
+ myTreeTable.getTree().updateUI();
+ updateOptionsAndDescriptionPanel();
+ }
+
@Override
protected void onScopeAdded() {
updateOptionsAndDescriptionPanel();
@@ -812,12 +820,19 @@ public class SingleInspectionProfilePanel extends JPanel {
}
@Override
- protected void onChange() {
+ protected void onSettingsChanged() {
myTreeTable.getTree().updateUI();
}
@Override
protected void onScopeAdded() {
+ updateOptionsAndDescriptionPanel();
+ }
+
+ @Override
+ protected void onScopesOrderChanged() {
+ myTreeTable.getTree().updateUI();
+ updateOptionsAndDescriptionPanel();
}
@Override
@@ -829,8 +844,9 @@ public class SingleInspectionProfilePanel extends JPanel {
});
- final ToolbarDecorator wrappedTable = ToolbarDecorator.createDecorator(scopesAndScopesAndSeveritiesTable);
+ final ToolbarDecorator wrappedTable = ToolbarDecorator.createDecorator(scopesAndScopesAndSeveritiesTable).disableUpDownActions();
final JPanel panel = wrappedTable.createPanel();
+ panel.setMinimumSize(new Dimension(getMinimumSize().width, 3 * scopesAndScopesAndSeveritiesTable.getRowHeight()));
severityPanel.add(new JBLabel("Scopes & Severities"),
new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
new Insets(5, 0, 2, 10), 0, 0));
@@ -842,8 +858,13 @@ public class SingleInspectionProfilePanel extends JPanel {
severityPanelWeightY = 0.3;
}
myOptionsPanel.add(severityPanel, new GridBagConstraints(0, 0, 1, 1, 1.0, severityPanelWeightY, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
- myOptionsPanel.add(configPanelAnchor, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH,
- new Insets(0, 0, 0, 0), 0, 0));
+ if (configPanelAnchor.getComponentCount() != 0) {
+ configPanelAnchor.setBorder(IdeBorderFactory.createTitledBorder("Options", false, new Insets(0, 0, 0, 0)));
+ }
+ if (configPanelAnchor.getComponentCount() != 0 || scopesNames.isEmpty()) {
+ myOptionsPanel.add(configPanelAnchor, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH,
+ new Insets(0, 0, 0, 0), 0, 0));
+ }
myOptionsPanel.revalidate();
GuiUtils.enableChildren(myOptionsPanel, isThoughOneNodeEnabled(nodes));
}
@@ -887,7 +908,10 @@ public class SingleInspectionProfilePanel extends JPanel {
private static void setConfigPanel(final JPanel configPanelAnchor, final ScopeToolState state) {
configPanelAnchor.removeAll();
- configPanelAnchor.add(state.getAdditionalConfigPanel());
+ final JComponent additionalConfigPanel = state.getAdditionalConfigPanel();
+ if (additionalConfigPanel != null) {
+ configPanelAnchor.add(ScrollPaneFactory.createScrollPane(additionalConfigPanel, SideBorder.NONE));
+ }
}
private static InspectionConfigTreeNode getGroupNode(InspectionConfigTreeNode root, String[] groupPath) {
@@ -1001,6 +1025,7 @@ public class SingleInspectionProfilePanel extends JPanel {
if (mySelectedProfile.isChanged()) return true;
if (myShareProfile != (mySelectedProfile.getProfileManager() == myProjectProfileManager)) return true;
if (!Comparing.strEqual(myInitialProfile, mySelectedProfile.getName())) return true;
+ if (!Comparing.equal(myInitialScopesOrder, mySelectedProfile.getScopesOrder())) return true;
if (descriptorsAreChanged()) {
return true;
}
@@ -1111,10 +1136,6 @@ public class SingleInspectionProfilePanel extends JPanel {
return false;
}
- public Tree getTreeTable() {
- return myTreeTable.getTree();
- }
-
public boolean isProfileShared() {
return myShareProfile;
}
@@ -1176,15 +1197,15 @@ public class SingleInspectionProfilePanel extends JPanel {
final boolean showOptionsAndDescriptorPanels,
@NotNull HighlightDisplayLevel level) {
final HighlightDisplayKey key = child.getDefaultDescriptor().getKey();
- mySelectedProfile.setErrorLevel(key, level, -1, myProjectProfileManager.getProject());
+ mySelectedProfile.setErrorLevel(key, level, null, myProjectProfileManager.getProject());
child.dropCache();
if (showOptionsAndDescriptorPanels) {
updateOptionsAndDescriptionPanel(new TreePath(child.getPath()));
}
}
- public JComponent getTree() {
- return myTreeTable.getTree();
+ public JComponent getPreferredFocusedComponent() {
+ return myTreeTable;
}
private class MyFilterComponent extends FilterComponent {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java
index cbd1c2482032..bccd2db28e21 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.daemon.impl.SeverityRegistrar;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.icons.AllIcons;
import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.actionSystem.ex.CheckboxAction;
@@ -60,6 +59,23 @@ public class InspectionFilterAction extends DefaultActionGroup {
addSeparator();
add(new ShowAvailableOnlyOnAnalyzeInspectionsAction());
+ add(new ShowOnlyCleanupInspectionsAction());
+ }
+
+ private class ShowOnlyCleanupInspectionsAction extends CheckboxAction {
+ public ShowOnlyCleanupInspectionsAction() {
+ super("Show Only Cleanup Inspections");
+ }
+
+ @Override
+ public boolean isSelected(final AnActionEvent e) {
+ return myInspectionsFilter.isShowOnlyCleanupInspections();
+ }
+
+ @Override
+ public void setSelected(final AnActionEvent e, final boolean state) {
+ myInspectionsFilter.setShowOnlyCleanupInspections(state);
+ }
}
private class ShowAvailableOnlyOnAnalyzeInspectionsAction extends CheckboxAction {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java
index 432ef560ba58..117cd774dff8 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionsFilter.java
@@ -33,11 +33,16 @@ public abstract class InspectionsFilter {
private final Set<HighlightSeverity> mySuitableSeverities = new HashSet<HighlightSeverity>();
private Boolean mySuitableInspectionsStates;
private boolean myAvailableOnlyForAnalyze;
+ private boolean myShowOnlyCleanupInspections;
public boolean isAvailableOnlyForAnalyze() {
return myAvailableOnlyForAnalyze;
}
+ public boolean isShowOnlyCleanupInspections() {
+ return myShowOnlyCleanupInspections;
+ }
+
public Boolean getSuitableInspectionsStates() {
return mySuitableInspectionsStates;
}
@@ -46,6 +51,11 @@ public abstract class InspectionsFilter {
return mySuitableSeverities.contains(severity);
}
+ public void setShowOnlyCleanupInspections(final boolean showOnlyCleanupInspections) {
+ myShowOnlyCleanupInspections = showOnlyCleanupInspections;
+ filterChanged();
+ }
+
public void setAvailableOnlyForAnalyze(final boolean availableOnlyForAnalyze) {
myAvailableOnlyForAnalyze = availableOnlyForAnalyze;
filterChanged();
@@ -67,10 +77,17 @@ public abstract class InspectionsFilter {
}
public boolean isEmptyFilter() {
- return mySuitableInspectionsStates == null && !myAvailableOnlyForAnalyze && mySuitableSeverities.isEmpty();
+ return mySuitableInspectionsStates == null
+ && !myAvailableOnlyForAnalyze
+ && !myShowOnlyCleanupInspections
+ && mySuitableSeverities.isEmpty();
}
public boolean matches(final Tools tools) {
+ if (myShowOnlyCleanupInspections && !tools.getTool().isCleanupTool()) {
+ return false;
+ }
+
if (mySuitableInspectionsStates != null && mySuitableInspectionsStates != tools.isEnabled()) {
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java
index 966a456e1d38..92cb62f0f800 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/InspectionsConfigTreeTable.java
@@ -28,17 +28,21 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.profile.codeInspection.ui.InspectionsAggregationUtil;
import com.intellij.profile.codeInspection.ui.table.ScopesAndSeveritiesTable;
import com.intellij.profile.codeInspection.ui.table.ThreeStateCheckBoxRenderer;
+import com.intellij.ui.DoubleClickListener;
import com.intellij.ui.treeStructure.treetable.TreeTable;
import com.intellij.ui.treeStructure.treetable.TreeTableModel;
+import com.intellij.ui.treeStructure.treetable.TreeTableTree;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
import java.awt.*;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
+import java.awt.event.*;
import java.util.*;
import java.util.List;
@@ -60,8 +64,8 @@ public class InspectionsConfigTreeTable extends TreeTable {
final TableColumn isEnabledColumn = getColumnModel().getColumn(IS_ENABLED_COLUMN);
isEnabledColumn.setMaxWidth(20);
- isEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer());
- isEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer());
+ isEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer(false));
+ isEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer(true));
addMouseMotionListener(new MouseAdapter() {
@Override
@@ -76,10 +80,42 @@ public class InspectionsConfigTreeTable extends TreeTable {
if (maybeIcon instanceof MultiScopeSeverityIcon) {
final LinkedHashMap<String, HighlightSeverity> scopeToAverageSeverityMap =
((MultiScopeSeverityIcon)maybeIcon).getScopeToAverageSeverityMap();
- IdeTooltipManager.getInstance().show(new IdeTooltip(InspectionsConfigTreeTable.this, point, new ScopesAndSeveritiesHintTable(scopeToAverageSeverityMap)), false);
+ IdeTooltipManager.getInstance().show(
+ new IdeTooltip(InspectionsConfigTreeTable.this, point, new ScopesAndSeveritiesHintTable(scopeToAverageSeverityMap)), false);
}
}
});
+
+ new DoubleClickListener() {
+ @Override
+ protected boolean onDoubleClick(MouseEvent event) {
+ final TreePath path = getTree().getPathForRow(getTree().getLeadSelectionRow());
+ if (path != null) {
+ final InspectionConfigTreeNode node = (InspectionConfigTreeNode)path.getLastPathComponent();
+ if (node.isLeaf()) {
+ swapInspectionEnableState();
+ }
+ }
+ return true;
+ }
+ }.installOn(this);
+
+ registerKeyboardAction(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ swapInspectionEnableState();
+ updateUI();
+ }
+ }, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), JComponent.WHEN_FOCUSED);
+
+ getEmptyText().setText("No enabled inspections available");
+ }
+
+ private void swapInspectionEnableState() {
+ for (int selectedRow : getSelectedRows()) {
+ final Object value = getValueAt(selectedRow, IS_ENABLED_COLUMN);
+ final boolean newValue = !Boolean.TRUE.equals(value);
+ setValueAt(newValue, selectedRow, IS_ENABLED_COLUMN);
+ }
}
public abstract static class InspectionsConfigTreeTableSettings {
@@ -107,6 +143,7 @@ public class InspectionsConfigTreeTable extends TreeTable {
private static class InspectionsConfigTreeTableModel extends DefaultTreeModel implements TreeTableModel {
private final InspectionsConfigTreeTableSettings mySettings;
+ private TreeTable myTreeTable;
public InspectionsConfigTreeTableModel(final InspectionsConfigTreeTableSettings settings) {
super(settings.getRoot());
@@ -154,7 +191,7 @@ public class InspectionsConfigTreeTable extends TreeTable {
mySettings.getInspectionProfile().getNonDefaultTools(toolId, mySettings.getProject()));
}
}
- return sink.constructIcon();
+ return sink.constructIcon(mySettings.getInspectionProfile());
} else if (column == IS_ENABLED_COLUMN) {
return isEnabled(inspectionsKeys);
}
@@ -195,26 +232,34 @@ public class InspectionsConfigTreeTable extends TreeTable {
aNode.dropCache();
mySettings.onChanged(aNode);
}
+ if (myTreeTable != null) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ public void run() {
+ ((AbstractTableModel)myTreeTable.getModel()).fireTableDataChanged();
+ }
+ });
+ }
}
@Override
public void setTree(final JTree tree) {
+ myTreeTable = ((TreeTableTree)tree).getTreeTable();
}
}
private static class MultiColoredHighlightSeverityIconSink {
- private final LinkedHashMap<String, HighlightSeverity> myScopeToAverageSeverityMap = new LinkedHashMap<String, HighlightSeverity>();
+ private final Map<String, HighlightSeverity> myScopeToAverageSeverityMap = new HashMap<String, HighlightSeverity>();
+ private String myDefaultScopeName;
private boolean myIsFirst = true;
- public Icon constructIcon() {
+ public Icon constructIcon(final InspectionProfileImpl inspectionProfile) {
if (myScopeToAverageSeverityMap.isEmpty()) {
return null;
}
- //TODO order scopes
return !allScopesHasMixedSeverity()
- ? new MultiScopeSeverityIcon(myScopeToAverageSeverityMap)
+ ? new MultiScopeSeverityIcon(myScopeToAverageSeverityMap, myDefaultScopeName, inspectionProfile)
: ScopesAndSeveritiesTable.MIXED_FAKE_LEVEL.getIcon();
}
@@ -229,6 +274,9 @@ public class InspectionsConfigTreeTable extends TreeTable {
public void put(final ScopeToolState defaultState, final Collection<ScopeToolState> nonDefault) {
putOne(defaultState);
+ if (myDefaultScopeName == null) {
+ myDefaultScopeName = defaultState.getScopeName();
+ }
for (final ScopeToolState scopeToolState : nonDefault) {
putOne(scopeToolState);
}
@@ -237,7 +285,7 @@ public class InspectionsConfigTreeTable extends TreeTable {
}
}
- public void putOne(final ScopeToolState state) {
+ private void putOne(final ScopeToolState state) {
final Icon icon = state.getLevel().getIcon();
final String scopeName = state.getScopeName();
if (icon instanceof HighlightDisplayLevel.SingleColorIconWithMask) {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java
index 6f093ca66349..099dbb622261 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/MultiScopeSeverityIcon.java
@@ -17,13 +17,15 @@ package com.intellij.profile.codeInspection.ui.inspectionsTree;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.profile.codeInspection.ui.ScopeOrderComparator;
import com.intellij.ui.JBColor;
import javax.swing.*;
import java.awt.*;
-import java.util.Collection;
-import java.util.LinkedHashMap;
+import java.util.*;
+import java.util.List;
/**
* @author Dmitry Batkovich
@@ -35,8 +37,17 @@ public class MultiScopeSeverityIcon implements Icon {
private final LinkedHashMap<String, HighlightSeverity> myScopeToAverageSeverityMap;
- public MultiScopeSeverityIcon(final LinkedHashMap<String, HighlightSeverity> scopeToAverageSeverityMap) {
- myScopeToAverageSeverityMap = scopeToAverageSeverityMap;
+ public MultiScopeSeverityIcon(final Map<String, HighlightSeverity> scopeToAverageSeverityMap,
+ final String defaultScopeName,
+ final InspectionProfileImpl inspectionProfile) {
+ final List<String> sortedScopeNames = new ArrayList<String>(scopeToAverageSeverityMap.keySet());
+ myScopeToAverageSeverityMap = new LinkedHashMap<String, HighlightSeverity>();
+ Collections.sort(sortedScopeNames, new ScopeOrderComparator(inspectionProfile));
+ sortedScopeNames.remove(defaultScopeName);
+ sortedScopeNames.add(defaultScopeName);
+ for (final String scopeName : sortedScopeNames) {
+ myScopeToAverageSeverityMap.put(scopeName, scopeToAverageSeverityMap.get(scopeName));
+ }
}
public LinkedHashMap<String, HighlightSeverity> getScopeToAverageSeverityMap() {
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java
index 05cb7ab193f5..68c7f20119bd 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/inspectionsTree/ScopesAndSeveritiesHintTable.java
@@ -19,10 +19,12 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel;
import com.intellij.ui.table.JBTable;
+import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableColumn;
import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
@@ -38,9 +40,20 @@ public class ScopesAndSeveritiesHintTable extends JBTable {
public ScopesAndSeveritiesHintTable(final LinkedHashMap<String, HighlightSeverity> scopeToAverageSeverityMap) {
super(new MyModel(scopeToAverageSeverityMap));
- final DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer();
- cellRenderer.setOpaque(false);
- getColumnModel().getColumn(SCOPE_COLUMN).setCellRenderer(cellRenderer);
+ getColumnModel().getColumn(SCOPE_COLUMN).setCellRenderer(new DefaultTableCellRenderer() {
+ @Override
+ public Component getTableCellRendererComponent(JTable table,
+ Object value,
+ boolean isSelected,
+ boolean hasFocus,
+ int row,
+ int column) {
+ super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+ setOpaque(false);
+ UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, this);
+ return this;
+ }
+ });
getColumnModel().getColumn(SEVERITY_COLUMN).setCellRenderer(new DefaultTableCellRenderer() {
@Override
@@ -55,6 +68,7 @@ public class ScopesAndSeveritiesHintTable extends JBTable {
setIcon(HighlightDisplayLevel.find(severity).getIcon());
setText(SingleInspectionProfilePanel.renderSeverity(severity));
setOpaque(false);
+ UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, this);
return this;
}
});
@@ -62,6 +76,16 @@ public class ScopesAndSeveritiesHintTable extends JBTable {
setRowSelectionAllowed(false);
setColumnSelectionAllowed(false);
setOpaque(false);
+
+ for (int i = 0; i < getColumnModel().getColumnCount(); i++) {
+ int w = 0;
+ final TableColumn column = getColumnModel().getColumn(i);
+ for (int j = 0; j < getModel().getRowCount(); j++) {
+ final Component component = prepareRenderer(column.getCellRenderer(), j, i);
+ w = Math.max(component.getPreferredSize().width, w);
+ }
+ column.setPreferredWidth(w);
+ }
}
private final static class MyModel extends AbstractTableModel {
@@ -96,7 +120,7 @@ public class ScopesAndSeveritiesHintTable extends JBTable {
@Override
public Object getValueAt(final int rowIndex, final int columnIndex) {
switch (columnIndex) {
- case SCOPE_COLUMN: return myScopes.get(rowIndex);
+ case SCOPE_COLUMN: return rowIndex < getRowCount() - 1 ? myScopes.get(rowIndex) : "Everywhere else";
case SEVERITY_COLUMN: return myScopeToAverageSeverityMap.get(myScopes.get(rowIndex));
default: throw new IllegalArgumentException();
}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java
index ad7dc946fff8..3b2c36bf7d34 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ScopesAndSeveritiesTable.java
@@ -17,20 +17,30 @@ package com.intellij.profile.codeInspection.ui.table;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
+import com.intellij.codeInspection.ex.Descriptor;
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.codeInspection.ex.ScopeToolState;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.DataManager;
import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.util.Comparing;
-import com.intellij.profile.codeInspection.ui.AddScopeUtil;
+import com.intellij.profile.codeInspection.ui.ScopeOrderComparator;
+import com.intellij.profile.codeInspection.ui.ScopesChooser;
import com.intellij.profile.codeInspection.ui.inspectionsTree.InspectionConfigTreeNode;
import com.intellij.psi.search.scope.packageSet.NamedScope;
+import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.table.JBTable;
import com.intellij.ui.treeStructure.treetable.TreeTable;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.Function;
import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.EditableModel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,8 +51,8 @@ import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
-import java.util.ArrayList;
-import java.util.LinkedHashSet;
+import java.awt.*;
+import java.util.*;
import java.util.List;
/**
@@ -66,8 +76,8 @@ public class ScopesAndSeveritiesTable extends JBTable {
final TableColumn scopeEnabledColumn = columnModel.getColumn(SCOPE_ENABLED_COLUMN);
scopeEnabledColumn.setMaxWidth(30);
- scopeEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer());
- scopeEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer());
+ scopeEnabledColumn.setCellRenderer(new ThreeStateCheckBoxRenderer(false));
+ scopeEnabledColumn.setCellEditor(new ThreeStateCheckBoxRenderer(true));
final TableColumn severityColumn = columnModel.getColumn(SEVERITY_COLUMN);
severityColumn.setCellRenderer(SeverityRenderer.create(tableSettings.getInspectionProfile()));
@@ -94,6 +104,8 @@ public class ScopesAndSeveritiesTable extends JBTable {
setStriped(true);
setShowGrid(false);
+
+ ((MyTableModel)getModel()).setTable(this);
}
public abstract static class TableSettings {
@@ -148,11 +160,13 @@ public class ScopesAndSeveritiesTable extends JBTable {
protected abstract void onScopeAdded();
+ protected abstract void onScopesOrderChanged();
+
protected abstract void onScopeRemoved(final int scopesCount);
protected abstract void onScopeChosen(final @NotNull ScopeToolState scopeToolState);
- protected abstract void onChange();
+ protected abstract void onSettingsChanged();
}
@NotNull
@@ -177,7 +191,9 @@ public class ScopesAndSeveritiesTable extends JBTable {
private final Project myProject;
private final TableSettings myTableSettings;
private final List<HighlightDisplayKey> myKeys;
+ private final Comparator<String> myScopeComparator;
+ private JTable myTable;
private String[] myScopeNames;
public MyTableModel(final TableSettings tableSettings) {
@@ -188,12 +204,24 @@ public class ScopesAndSeveritiesTable extends JBTable {
myKeyNames = tableSettings.getKeyNames();
myNodes = tableSettings.getNodes();
myTreeTable = tableSettings.getTreeTable();
+ myScopeComparator = new ScopeOrderComparator(myInspectionProfile);
refreshAggregatedScopes();
}
+ public void setTable(JTable table) {
+ myTable = table;
+ }
+
@Override
public boolean isCellEditable(final int rowIndex, final int columnIndex) {
- return columnIndex != SCOPE_NAME_COLUMN;
+ if (columnIndex == SCOPE_NAME_COLUMN) {
+ return false;
+ } else if (columnIndex == SCOPE_ENABLED_COLUMN) {
+ return true;
+ }
+ assert columnIndex == SEVERITY_COLUMN;
+ final ExistedScopesStatesAndNonExistNames scopeToolState = getScopeToolState(rowIndex);
+ return scopeToolState.getNonExistNames().isEmpty();
}
@Override
@@ -221,7 +249,7 @@ public class ScopesAndSeveritiesTable extends JBTable {
return String.class;
}
if (SEVERITY_COLUMN == columnIndex) {
- return HighlightSeverity.class;
+ return SeverityState.class;
}
throw new IllegalArgumentException();
}
@@ -235,9 +263,9 @@ public class ScopesAndSeveritiesTable extends JBTable {
case SCOPE_ENABLED_COLUMN:
return isEnabled(rowIndex);
case SCOPE_NAME_COLUMN:
- return getScope(rowIndex).getName();
+ return rowIndex == lastRowIndex() ? "Everywhere else" : getScope(rowIndex).getName();
case SEVERITY_COLUMN:
- return getSeverity(rowIndex);
+ return getSeverityState(rowIndex);
default:
throw new IllegalArgumentException("Invalid column index " + columnIndex);
}
@@ -248,12 +276,12 @@ public class ScopesAndSeveritiesTable extends JBTable {
}
@NotNull
- private HighlightSeverity getSeverity(final int rowIndex) {
+ private SeverityState getSeverityState(final int rowIndex) {
final ExistedScopesStatesAndNonExistNames existedScopesStatesAndNonExistNames = getScopeToolState(rowIndex);
if (!existedScopesStatesAndNonExistNames.getNonExistNames().isEmpty()) {
- return MIXED_FAKE_SEVERITY;
+ return new SeverityState(MIXED_FAKE_SEVERITY, false);
}
- return ScopesAndSeveritiesTable.getSeverity(existedScopesStatesAndNonExistNames.getExistedStates());
+ return new SeverityState(ScopesAndSeveritiesTable.getSeverity(existedScopesStatesAndNonExistNames.getExistedStates()), true);
}
@Nullable
@@ -314,6 +342,7 @@ public class ScopesAndSeveritiesTable extends JBTable {
}
}
myScopeNames = ArrayUtil.toStringArray(scopesNames);
+ Arrays.sort(myScopeNames, myScopeComparator);
}
private int lastRowIndex() {
@@ -326,13 +355,14 @@ public class ScopesAndSeveritiesTable extends JBTable {
return;
}
if (columnIndex == SEVERITY_COLUMN) {
- final HighlightDisplayLevel level = HighlightDisplayLevel.find(((HighlightSeverity)value).getName());
+ final SeverityState severityState = (SeverityState)value;
+ final HighlightDisplayLevel level = HighlightDisplayLevel.find(severityState.getSeverity().getName());
if (level == null) {
- LOG.error("no display level found for name " + ((HighlightSeverity)value).getName());
+ LOG.error("no display level found for name " + severityState.getSeverity().getName());
return;
}
- final int idx = rowIndex == lastRowIndex() ? -1 : rowIndex;
- myInspectionProfile.setErrorLevel(myKeys, level, idx, myProject);
+ final String scopeName = rowIndex == lastRowIndex() ? null : getScope(rowIndex).getName();
+ myInspectionProfile.setErrorLevel(myKeys, level, scopeName, myProject);
}
else if (columnIndex == SCOPE_ENABLED_COLUMN) {
final NamedScope scope = getScope(rowIndex);
@@ -354,7 +384,7 @@ public class ScopesAndSeveritiesTable extends JBTable {
}
}
}
- myTableSettings.onChange();
+ myTableSettings.onSettingsChanged();
}
@Override
@@ -368,9 +398,31 @@ public class ScopesAndSeveritiesTable extends JBTable {
@Override
public void addRow() {
- AddScopeUtil.performAddScope(myTreeTable, myProject, myInspectionProfile, myNodes);
- myTableSettings.onScopeAdded();
- refreshAggregatedScopes();
+ final List<Descriptor> descriptors = ContainerUtil.map(myTableSettings.getNodes(), new Function<InspectionConfigTreeNode, Descriptor>() {
+ @Override
+ public Descriptor fun(InspectionConfigTreeNode inspectionConfigTreeNode) {
+ return inspectionConfigTreeNode.getDefaultDescriptor();
+ }
+ });
+ final ScopesChooser scopesChooser = new ScopesChooser(descriptors, myInspectionProfile, myProject, myScopeNames) {
+ @Override
+ protected void onScopeAdded() {
+ myTableSettings.onScopeAdded();
+ refreshAggregatedScopes();
+ }
+
+ @Override
+ protected void onScopesOrderChanged() {
+ myTableSettings.onScopesOrderChanged();
+ }
+ };
+ DataContext dataContext = DataManager.getInstance().getDataContext(myTable);
+ final JComponent component = (JComponent)PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
+ final ListPopup popup = JBPopupFactory.getInstance()
+ .createActionGroupPopup(ScopesChooser.TITLE, scopesChooser.createPopupActionGroup(myTable), dataContext,
+ JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false);
+ final RelativePoint point = new RelativePoint(myTable, new Point(myTable.getWidth() - popup.getContent().getPreferredSize().width, 0));
+ popup.show(point);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java
index 2fe95e6d7224..e1b3d54b8fb7 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java
@@ -22,6 +22,8 @@ import com.intellij.openapi.ui.ComboBoxTableRenderer;
import com.intellij.profile.codeInspection.SeverityProvider;
import com.intellij.profile.codeInspection.ui.LevelChooserAction;
import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -32,33 +34,40 @@ import java.util.SortedSet;
/**
* @author Dmitry Batkovich
*/
-public class SeverityRenderer extends ComboBoxTableRenderer<HighlightSeverity> {
- public SeverityRenderer(final HighlightSeverity[] values) {
+public class SeverityRenderer extends ComboBoxTableRenderer<SeverityState> {
+ public SeverityRenderer(final SeverityState[] values) {
super(values);
}
public static SeverityRenderer create(final InspectionProfileImpl inspectionProfile) {
final SortedSet<HighlightSeverity> severities =
LevelChooserAction.getSeverities(((SeverityProvider)inspectionProfile.getProfileManager()).getOwnSeverityRegistrar());
- return new SeverityRenderer(severities.toArray(new HighlightSeverity[severities.size()]));
+ return new SeverityRenderer(ContainerUtil.map2Array(severities, new SeverityState[severities.size()], new Function<HighlightSeverity, SeverityState>() {
+ @Override
+ public SeverityState fun(HighlightSeverity severity) {
+ return new SeverityState(severity, true);
+ }
+ }));
}
+ @Override
+ protected void customizeComponent(SeverityState value, JTable table, boolean isSelected) {
+ super.customizeComponent(value, table, isSelected);
+ setPaintArrow(value.isEnabledForEditing());
+ }
@Override
- protected String getTextFor(@NotNull final HighlightSeverity value) {
- return SingleInspectionProfilePanel.renderSeverity(value);
+ protected String getTextFor(@NotNull final SeverityState value) {
+ return SingleInspectionProfilePanel.renderSeverity(value.getSeverity());
}
@Override
- protected Icon getIconFor(@NotNull final HighlightSeverity value) {
- return HighlightDisplayLevel.find(value).getIcon();
+ protected Icon getIconFor(@NotNull final SeverityState value) {
+ return HighlightDisplayLevel.find(value.getSeverity()).getIcon();
}
@Override
public boolean isCellEditable(final EventObject event) {
- if (event instanceof MouseEvent) {
- return ((MouseEvent)event).getClickCount() >= 1;
- }
- return true;
+ return !(event instanceof MouseEvent) || ((MouseEvent)event).getClickCount() >= 1;
}
}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java
new file mode 100644
index 000000000000..2aefde070af7
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityState.java
@@ -0,0 +1,40 @@
+/*
+ * 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.profile.codeInspection.ui.table;
+
+import com.intellij.lang.annotation.HighlightSeverity;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class SeverityState {
+
+ private final HighlightSeverity mySeverity;
+ private final boolean myEnabledForEditing;
+
+ public SeverityState(HighlightSeverity severity, boolean enabledForEditing) {
+ mySeverity = severity;
+ myEnabledForEditing = enabledForEditing;
+ }
+
+ public HighlightSeverity getSeverity() {
+ return mySeverity;
+ }
+
+ public boolean isEnabledForEditing() {
+ return myEnabledForEditing;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java
index 7d8cfdfc9db5..455e2a60cd19 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/ThreeStateCheckBoxRenderer.java
@@ -15,11 +15,9 @@
*/
package com.intellij.profile.codeInspection.ui.table;
-import com.intellij.ui.ClickListener;
import com.intellij.util.SmartList;
import com.intellij.util.ui.ThreeStateCheckBox;
import com.intellij.util.ui.UIUtil;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -28,7 +26,7 @@ import javax.swing.event.ChangeEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
-import java.awt.event.MouseEvent;
+import java.awt.event.*;
import java.util.EventObject;
import java.util.List;
@@ -39,10 +37,16 @@ public class ThreeStateCheckBoxRenderer extends ThreeStateCheckBox implements Ta
private final List<CellEditorListener> myListeners = new SmartList<CellEditorListener>();
- public ThreeStateCheckBoxRenderer() {
+ public ThreeStateCheckBoxRenderer(final boolean isEditor) {
setThirdStateEnabled(false);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
+ addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ stopCellEditing();
+ }
+ });
}
@Override
@@ -69,16 +73,6 @@ public class ThreeStateCheckBoxRenderer extends ThreeStateCheckBox implements Ta
} else {
setSelected((Boolean) value);
}
- new ClickListener() {
- @Override
- public boolean onClick(@NotNull final MouseEvent event, final int clickCount) {
- if (clickCount == 1) {
- stopCellEditing();
- return true;
- }
- return false;
- }
- }.installOn(this);
return this;
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java b/platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
deleted file mode 100644
index 2add3ed1b3c5..000000000000
--- a/platform/lang-impl/src/com/intellij/psi/impl/search/LexerEditorHighlighterLexer.java
+++ /dev/null
@@ -1,133 +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.psi.impl.search;
-
-import com.intellij.lexer.Lexer;
-import com.intellij.lexer.LexerBase;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.highlighter.EditorHighlighter;
-import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
-import com.intellij.openapi.editor.highlighter.HighlighterIterator;
-import com.intellij.openapi.editor.impl.EditorHighlighterCache;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
-import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.util.text.CharSequenceSubSequence;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
-* @author Sergey Evdokimov
-*/
-public class LexerEditorHighlighterLexer extends LexerBase {
- private HighlighterIterator iterator;
- private CharSequence buffer;
- private int start;
- private int end;
- private final EditorHighlighter myHighlighter;
- private final boolean myAlreadyInitializedHighlighter;
-
- public LexerEditorHighlighterLexer(final EditorHighlighter highlighter, boolean alreadyInitializedHighlighter) {
- myHighlighter = highlighter;
- myAlreadyInitializedHighlighter = alreadyInitializedHighlighter;
- }
-
- @Nullable
- public static Lexer getLexerBasedOnLexerHighlighter(CharSequence text, VirtualFile virtualFile, Project project) {
- EditorHighlighter highlighter = null;
-
- PsiFile psiFile = virtualFile != null ? PsiManager.getInstance(project).findFile(virtualFile) : null;
- final Document document = psiFile != null ? PsiDocumentManager.getInstance(project).getDocument(psiFile) : null;
- final EditorHighlighter cachedEditorHighlighter;
- boolean alreadyInitializedHighlighter = false;
-
- if (document != null &&
- (cachedEditorHighlighter = EditorHighlighterCache.getEditorHighlighterForCachesBuilding(document)) != null &&
- PlatformIdTableBuilding.checkCanUseCachedEditorHighlighter(text, cachedEditorHighlighter)) {
- highlighter = cachedEditorHighlighter;
- alreadyInitializedHighlighter = true;
- }
- else if (virtualFile != null) {
- highlighter = EditorHighlighterFactory.getInstance().createEditorHighlighter(project, virtualFile);
- }
-
- if (highlighter != null) {
- return new LexerEditorHighlighterLexer(highlighter, alreadyInitializedHighlighter);
- }
- return null;
- }
-
- @Override
- public void start(@NotNull CharSequence buffer, int startOffset, int endOffset, int state) {
- if (myAlreadyInitializedHighlighter) {
- this.buffer = buffer;
- start = startOffset;
- end = endOffset;
- } else {
- myHighlighter.setText(new CharSequenceSubSequence(this.buffer = buffer, start = startOffset, end = endOffset));
- }
- iterator = myHighlighter.createIterator(0);
- }
-
- public void resetPosition(int offset) {
- iterator = myHighlighter.createIterator(offset);
- }
-
- @Override
- public int getState() {
- return 0;
- }
-
- @Override
- public IElementType getTokenType() {
- if (iterator.atEnd()) return null;
- return iterator.getTokenType();
- }
-
- @Override
- public int getTokenStart() {
- return iterator.getStart();
- }
-
- @Override
- public int getTokenEnd() {
- return iterator.getEnd();
- }
-
- @Override
- public void advance() {
- iterator.advance();
- }
-
- @NotNull
- @Override
- public CharSequence getBufferSequence() {
- return buffer;
- }
-
- @Override
- public int getBufferEnd() {
- return end;
- }
-
- public HighlighterIterator getHighlighterIterator() {
- return iterator;
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
index 1b17faf21905..42dcb46c7ac0 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerRunnable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 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.
@@ -149,7 +149,7 @@ abstract class CodeStyleManagerRunnable<T> {
SourceTreeToPsiMap.psiElementToTree(CodeStyleManagerImpl.findElementInTreeWithFormatterEnabled(file, offset));
if (elementAtOffset == null) {
int significantRangeStart = CharArrayUtil.shiftBackward(file.getText(), offset - 1, "\r\t ");
- return new TextRange(significantRangeStart, offset);
+ return new TextRange(Math.max(significantRangeStart, 0), offset);
}
final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
index 27089fa70e91..fdc434d8d11a 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
@@ -16,6 +16,7 @@
package com.intellij.psi.impl.source.tree.injected;
+import com.intellij.extapi.psi.PsiFileBase;
import com.intellij.injected.editor.*;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageUtil;
@@ -48,8 +49,10 @@ import java.util.List;
* @author cdr
*/
public class InjectedLanguageUtil {
- static final Key<List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>>> HIGHLIGHT_TOKENS = Key.create("HIGHLIGHT_TOKENS");
- public static Key<Boolean> FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION"); // meaning: injected file text is probably incorrect
+ static final Key<List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>>> HIGHLIGHT_TOKENS =
+ Key.create("HIGHLIGHT_TOKENS");
+ public static Key<Boolean> FRANKENSTEIN_INJECTION = Key.create("FRANKENSTEIN_INJECTION");
+ // meaning: injected file text is probably incorrect
public static void forceInjectionOnElement(@NotNull PsiElement host) {
enumerate(host, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@@ -113,9 +116,9 @@ public class InjectedLanguageUtil {
* @return true if enumerated successfully
*/
public static boolean enumerate(@NotNull PsiElement host,
- @NotNull PsiFile containingFile,
- boolean probeUp,
- @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
+ @NotNull PsiFile containingFile,
+ boolean probeUp,
+ @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
//do not inject into nonphysical files except during completion
if (!containingFile.isPhysical() && containingFile.getOriginalFile() == containingFile) {
final PsiElement context = InjectedLanguageManager.getInstance(containingFile.getProject()).getInjectionHost(containingFile);
@@ -175,6 +178,32 @@ public class InjectedLanguageUtil {
return null;
}
+ /**
+ * Finds injected language in expression
+ *
+ * @param expression where to find
+ * @param classToFind class that represents language we look for
+ * @param <T> class that represents language we look for
+ * @return instance of class that represents language we look for or null of not found
+ */
+ @Nullable
+ @SuppressWarnings("unchecked") // We check types dynamically (using isAssignableFrom)
+ public static <T extends PsiFileBase> T findInjectedFile(@NotNull final PsiElement expression,
+ @NotNull final Class<T> classToFind) {
+ final List<Pair<PsiElement, TextRange>> files =
+ InjectedLanguageManager.getInstance(expression.getProject()).getInjectedPsiFiles(expression);
+ if (files == null) {
+ return null;
+ }
+ for (final Pair<PsiElement, TextRange> fileInfo : files) {
+ final PsiElement injectedFile = fileInfo.first;
+ if (classToFind.isAssignableFrom(injectedFile.getClass())) {
+ return (T)injectedFile;
+ }
+ }
+ return null;
+ }
+
public static Editor getEditorForInjectedLanguageNoCommit(@Nullable Editor editor, @Nullable PsiFile file, final int offset) {
if (editor == null || file == null || editor instanceof EditorWindow) return editor;
PsiFile injectedFile = findInjectedPsiNoCommit(file, offset);
@@ -200,7 +229,9 @@ public class InjectedLanguageUtil {
}
}
}
- if (!documentWindow.isValid()) return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied
+ if (!documentWindow.isValid()) {
+ return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied
+ }
return EditorWindowImpl.create(documentWindow, (EditorImpl)hostEditor, injectedFile);
}
@@ -284,7 +315,8 @@ public class InjectedLanguageUtil {
ParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement> cachedValue =
CachedValuesManager.getManager(project).createParameterizedCachedValue(INJECTED_PSI_PROVIDER, false);
- CachedValueProvider.Result<MultiHostRegistrarImpl> result = CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar);
+ CachedValueProvider.Result<MultiHostRegistrarImpl> result =
+ CachedValueProvider.Result.create(registrar, PsiModificationTracker.MODIFICATION_COUNT, registrar);
((PsiParameterizedCachedValue<MultiHostRegistrarImpl, PsiElement>)cachedValue).setValue(result);
e.putUserData(INJECTED_PSI, cachedValue);
@@ -307,7 +339,9 @@ public class InjectedLanguageUtil {
// returns (injected psi, leaf element at the offset, language of the leaf element)
// since findElementAt() is expensive, we trying to reuse its result
@NotNull
- private static Trinity<PsiElement,PsiElement,Language> tryOffset(@NotNull PsiFile hostFile, final int offset, @NotNull PsiDocumentManager documentManager) {
+ private static Trinity<PsiElement, PsiElement, Language> tryOffset(@NotNull PsiFile hostFile,
+ final int offset,
+ @NotNull PsiDocumentManager documentManager) {
FileViewProvider provider = hostFile.getViewProvider();
Language leafLanguage = null;
PsiElement leafElement = null;
@@ -319,11 +353,11 @@ public class InjectedLanguageUtil {
leafElement = element;
}
PsiElement injected = findInside(element, hostFile, offset, documentManager);
- if (injected != null) return Trinity.create(injected,element, language);
+ if (injected != null) return Trinity.create(injected, element, language);
}
// maybe we are at the border between two psi elements, then try to find injection at the end of the left element
if (offset != 0 && (element == null || element.getTextRange().getStartOffset() == offset)) {
- PsiElement leftElement = provider.findElementAt(offset-1, language);
+ PsiElement leftElement = provider.findElementAt(offset - 1, language);
if (leftElement != null && leftElement.getTextRange().getEndOffset() == offset) {
PsiElement injected = findInside(leftElement, hostFile, offset, documentManager);
if (injected != null) return Trinity.create(injected, element, language);
@@ -334,7 +368,10 @@ public class InjectedLanguageUtil {
return Trinity.create(null, leafElement, leafLanguage);
}
- private static PsiElement findInside(@NotNull PsiElement element, @NotNull PsiFile hostFile, final int hostOffset, @NotNull final PsiDocumentManager documentManager) {
+ private static PsiElement findInside(@NotNull PsiElement element,
+ @NotNull PsiFile hostFile,
+ final int hostOffset,
+ @NotNull final PsiDocumentManager documentManager) {
final Ref<PsiElement> out = new Ref<PsiElement>();
enumerate(element, hostFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
@Override
@@ -361,10 +398,12 @@ public class InjectedLanguageUtil {
// modification of cachedInjectedDocuments must be under PsiLock only
ConcurrentList<DocumentWindow> injected = hostPsiFile.getUserData(INJECTED_DOCS_KEY);
if (injected == null) {
- injected = ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createConcurrentList());
+ injected =
+ ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createConcurrentList());
}
return injected;
}
+
public static void clearCachedInjectedFragmentsForFile(@NotNull PsiFile file) {
file.putUserData(INJECTED_DOCS_KEY, null);
}
@@ -426,10 +465,12 @@ public class InjectedLanguageUtil {
}
return containingFile;
}
+
@NotNull
public static Editor getTopLevelEditor(@NotNull Editor editor) {
return editor instanceof EditorWindow ? ((EditorWindow)editor).getDelegate() : editor;
}
+
public static boolean isInInjectedLanguagePrefixSuffix(@NotNull final PsiElement element) {
PsiFile injectedFile = element.getContainingFile();
if (injectedFile == null) return false;
@@ -461,13 +502,13 @@ public class InjectedLanguageUtil {
public static String getUnescapedText(PsiFile file, @Nullable final PsiElement startElement, @Nullable final PsiElement endElement) {
final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(file.getProject());
if (manager.getInjectionHost(file) == null) {
- return file.getText().substring(startElement == null? 0 : startElement.getTextRange().getStartOffset(),
- endElement == null? file.getTextLength() : endElement.getTextRange().getStartOffset());
+ return file.getText().substring(startElement == null ? 0 : startElement.getTextRange().getStartOffset(),
+ endElement == null ? file.getTextLength() : endElement.getTextRange().getStartOffset());
}
final StringBuilder sb = new StringBuilder();
file.accept(new PsiRecursiveElementWalkingVisitor() {
- Boolean myState = startElement == null? Boolean.TRUE : null;
+ Boolean myState = startElement == null ? Boolean.TRUE : null;
@Override
public void visitElement(PsiElement element) {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java
index 99ac9f7ec586..232ddd7bec3b 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/KeyboardComboSwitcher.java
@@ -28,7 +28,7 @@ public class KeyboardComboSwitcher {
if (toggleStrategy) {
final int size = comboBox.getModel().getSize();
int next = comboBox.getSelectedIndex() + 1;
- if (next < 0 || next >= size) {
+ if (size > 0 && (next < 0 || next >= size)) {
if (!UISettings.getInstance().CYCLE_SCROLLING) {
return;
}
diff --git a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
index 1301079a1967..6e37711a9493 100644
--- a/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/ui/popup/util/DetailViewImpl.java
@@ -151,6 +151,7 @@ public class DetailViewImpl extends JPanel implements DetailView, UserDataHolder
getEditor().getSettings().setRefrainFromScrolling(false);
getEditor().getSettings().setLineNumbersShown(true);
getEditor().getSettings().setFoldingOutlineShown(false);
+ ((EditorEx)getEditor()).getFoldingModel().setFoldingEnabled(false);
add(getEditor().getComponent(), BorderLayout.CENTER);
}
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java b/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java
index 34f80dae5cc9..451b0e7c1954 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/ContentHashesSupport.java
@@ -84,7 +84,7 @@ class ContentHashesSupport {
messageDigest.update((byte)0);
messageDigest.update(String.valueOf(bytes.length).getBytes(defaultCharset));
messageDigest.update((byte)0);
- messageDigest.update((charset != null ? charset.displayName():"null_charset").getBytes(defaultCharset));
+ messageDigest.update((charset != null ? charset.name():"null_charset").getBytes(defaultCharset));
messageDigest.update((byte)0);
messageDigest.update(bytes, 0, bytes.length);
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java b/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java
index 6c866ad2283f..09aeea33b71e 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/DebugAssertions.java
@@ -31,7 +31,7 @@ public class DebugAssertions {
public static final boolean EXTRA_SANITY_CHECKS = SystemProperties.getBooleanProperty(
"intellij.idea.indices.debug.extra.sanity",
- true
+ DEBUG
);
public static void assertTrue(boolean value) {
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
index 5242ee3b70cf..85077380ea6e 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -1964,33 +1964,38 @@ public class FileBasedIndexImpl extends FileBasedIndex {
// For 'normal indices' schedule the file for update and reset stamps for all affected indices (there
// can be client that used indices between before and after events, in such case indices are up to date due to force update
// with old content)
- if (!fileIsDirectory && !isTooLarge(file)) {
- FileTypeManagerImpl.cacheFileType(file, file.getFileType());
- try {
- final List<ID<?, ?>> candidates = getAffectedIndexCandidates(file);
- //noinspection ForLoopReplaceableByForEach
- boolean scheduleForUpdate = false;
- boolean resetStamp = false;
-
- //noinspection ForLoopReplaceableByForEach
- for (int i = 0, size = candidates.size(); i < size; ++i) {
- final ID<?, ?> indexId = candidates.get(i);
- if (needsFileContentLoading(indexId) && getInputFilter(indexId).acceptInput(file)) {
- if (IndexingStamp.isFileIndexedStateCurrent(file, indexId)) {
- IndexingStamp.setFileIndexedStateOutdated(file, indexId);
- resetStamp = true;
+ if (!fileIsDirectory) {
+ if (isTooLarge(file)) {
+ // large file might be scheduled for update in before event when its size was not large
+ myChangedFilesCollector.myFilesToUpdate.remove(file);
+ } else {
+ FileTypeManagerImpl.cacheFileType(file, file.getFileType());
+ try {
+ final List<ID<?, ?>> candidates = getAffectedIndexCandidates(file);
+ //noinspection ForLoopReplaceableByForEach
+ boolean scheduleForUpdate = false;
+ boolean resetStamp = false;
+
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0, size = candidates.size(); i < size; ++i) {
+ final ID<?, ?> indexId = candidates.get(i);
+ if (needsFileContentLoading(indexId) && getInputFilter(indexId).acceptInput(file)) {
+ if (IndexingStamp.isFileIndexedStateCurrent(file, indexId)) {
+ IndexingStamp.setFileIndexedStateOutdated(file, indexId);
+ resetStamp = true;
+ }
+ scheduleForUpdate = true;
}
- scheduleForUpdate = true;
}
- }
- if (scheduleForUpdate) {
- if (resetStamp) IndexingStamp.flushCache(file);
- scheduleForUpdate(file);
+ if (scheduleForUpdate) {
+ if (resetStamp) IndexingStamp.flushCache(file);
+ scheduleForUpdate(file);
+ }
+ }
+ finally {
+ FileTypeManagerImpl.cacheFileType(file, null);
}
- }
- finally {
- FileTypeManagerImpl.cacheFileType(file, null);
}
}
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
index 6bdd55b1d343..5ef1379eaaf4 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
@@ -59,7 +59,7 @@ public class IndexingStamp {
private static final long UNINDEXED_STAMP = -1L; // we don't store trivial "absent" state
private static final long INDEX_DATA_OUTDATED_STAMP = -2L;
- private static final int VERSION = 12;
+ private static final int VERSION = 13;
private static final ConcurrentHashMap<ID<?, ?>, Long> ourIndexIdToCreationStamp = new ConcurrentHashMap<ID<?, ?>, Long>();
private static volatile long ourLastStamp; // ensure any file index stamp increases
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
index ebb7911e82be..6427765295c5 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
@@ -354,7 +354,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
FileContent fileContent = (FileContent)content;
hashId = getHashOfContent(fileContent);
if (doReadSavedPersistentData) {
- if (!myContents.isBusyReading()) { // avoid blocking read, we can calculate index value
+ if (!myContents.isBusyReading() || DebugAssertions.EXTRA_SANITY_CHECKS) { // avoid blocking read, we can calculate index value
ByteSequence bytes = myContents.get(hashId);
if (bytes != null) {
data = deserializeSavedPersistentData(bytes);
@@ -367,7 +367,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
"Unexpected difference in indexing of %s by index %s, file type %s, charset %s\ndiff %s\nprevious indexed info %s",
fileContent.getFile(),
myIndexId,
- fileContent.getFileType(),
+ fileContent.getFileType().getName(),
((FileContentImpl)fileContent).getCharset(),
buildDiff(data, contentData),
myIndexingTrace.get(hashId)
@@ -396,7 +396,7 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
FileContent fileContent = (FileContent)content;
try {
- myIndexingTrace.put(hashId, ((FileContentImpl)fileContent).getCharset() + "," + fileContent.getFileType()+"," + fileContent.getFile().getPath() + "," +
+ myIndexingTrace.put(hashId, ((FileContentImpl)fileContent).getCharset() + "," + fileContent.getFileType().getName()+"," + fileContent.getFile().getPath() + "," +
ExceptionUtil.getThrowableText(new Throwable()));
} catch (IOException ex) {
LOG.error(ex);
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
index 18961ca843c3..fcbaa21f330b 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
@@ -1,3 +1,18 @@
+/*
+ * 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.webcore.packaging;
import com.intellij.icons.AllIcons;
@@ -93,6 +108,7 @@ public class ManagePackagesDialog extends DialogWrapper {
public void run() {
try {
myController.reloadAllPackages();
+ initModel();
myPackages.setPaintBusy(false);
}
catch (final IOException e) {
@@ -310,6 +326,7 @@ public class ManagePackagesDialog extends DialogWrapper {
@Override
public void run() {
myPackages.setModel(myPackagesModel);
+ ((MyPackageFilter)myFilter).filter();
doSelectPackage(mySelectedPackageName);
setDownloadStatus(false);
}
@@ -473,6 +490,7 @@ public class ManagePackagesDialog extends DialogWrapper {
final Object pyPackage = myPackages.getSelectedValue();
if (pyPackage instanceof RepoPackage) {
final String packageName = ((RepoPackage)pyPackage).getName();
+ mySelectedPackageName = packageName;
myVersionComboBox.removeAllItems();
if (myVersionCheckBox.isEnabled()) {
myController.fetchPackageVersions(packageName, new CatchingConsumer<List<String>, Exception>() {
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java b/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java
index cb281cb3d7af..1513bb451aa2 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/PackagesNotificationPanel.java
@@ -8,6 +8,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.HyperlinkAdapter;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.components.JBLabel;
+import com.intellij.util.ui.SwingHelper;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -22,18 +23,17 @@ import java.util.Map;
* @author yole
*/
public class PackagesNotificationPanel {
- private final JEditorPane myEditorPane = new MyNotificationPane();
private final Project myProject;
+ private final JEditorPane myHtmlViewer;
private final Map<String, Runnable> myLinkHandlers = new HashMap<String, Runnable>();
private String myErrorTitle;
private String myErrorDescription;
- public PackagesNotificationPanel(Project project) {
+ public PackagesNotificationPanel(@NotNull Project project) {
myProject = project;
- myEditorPane.setBackground(UIManager.getColor("ArrowButton.background"));
- myEditorPane.setContentType("text/html");
- myEditorPane.setEditable(false);
- myEditorPane.addHyperlinkListener(new HyperlinkAdapter() {
+ myHtmlViewer = SwingHelper.createHtmlViewer(true, null, null, null);
+ myHtmlViewer.setVisible(false);
+ myHtmlViewer.addHyperlinkListener(new HyperlinkAdapter() {
@Override
protected void hyperlinkActivated(HyperlinkEvent e) {
final Runnable handler = myLinkHandlers.get(e.getDescription());
@@ -76,11 +76,18 @@ public class PackagesNotificationPanel {
public void showResult(String packageName, @Nullable String errorDescription) {
if (StringUtil.isEmpty(errorDescription)) {
- showSuccess("Package successfully installed.");
+ String message = "Package installed successfully";
+ if (packageName != null) {
+ message = "Package '" + packageName + "' installed successfully";
+ }
+ showSuccess(message);
}
else {
- String title = "Install packages failed";
- final String firstLine = title + ": Error occurred when installing package " + packageName + ". ";
+ String title = "Failed to install packages";
+ if (packageName != null) {
+ title = "Failed to install package '" + packageName + "'";
+ }
+ String firstLine = "Error occurred when installing package '" + packageName + "'. ";
showError(firstLine + "<a href=\"xxx\">Details...</a>",
title,
firstLine + errorDescription);
@@ -96,19 +103,18 @@ public class PackagesNotificationPanel {
}
public JComponent getComponent() {
- return myEditorPane;
+ return myHtmlViewer;
}
public void showSuccess(String text) {
showContent(text, MessageType.INFO.getPopupBackground());
}
- private void showContent(String text, final Color background) {
- myEditorPane.removeAll();
+ private void showContent(@NotNull String text, @NotNull Color background) {
String htmlText = text.startsWith("<html>") ? text : UIUtil.toHtml(text);
- myEditorPane.setText(htmlText);
- myEditorPane.setBackground(background);
- myEditorPane.setVisible(true);
+ myHtmlViewer.setText(htmlText);
+ myHtmlViewer.setBackground(background);
+ setVisibleEditorPane(true);
myErrorTitle = null;
myErrorDescription = null;
}
@@ -124,22 +130,20 @@ public class PackagesNotificationPanel {
}
public void hide() {
- myEditorPane.setVisible(false);
+ setVisibleEditorPane(false);
}
- public boolean hasLinkHandler(String key) {
- return myLinkHandlers.containsKey(key);
+ private void setVisibleEditorPane(boolean visible) {
+ boolean oldVisible = myHtmlViewer.isVisible();
+ myHtmlViewer.setVisible(visible);
+ if (oldVisible != visible) {
+ myHtmlViewer.revalidate();
+ myHtmlViewer.repaint();
+ }
}
- private static class MyNotificationPane extends JEditorPane {
- @Override
- public Dimension getPreferredSize() {
- // This trick makes text component to carry text over to the next line
- // iff the text line width exceeds parent's width
- Dimension dimension = super.getPreferredSize();
- dimension.width = 0;
- return dimension;
- }
+ public boolean hasLinkHandler(String key) {
+ return myLinkHandlers.containsKey(key);
}
public void removeLinkHandler(String key) {
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java
new file mode 100644
index 000000000000..f1733f5e6d06
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace-after.java
@@ -0,0 +1,4 @@
+class A {
+ void foo() {
+ }
+<caret>}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java
new file mode 100644
index 000000000000..5fd42398e146
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/beforeBrace.java
@@ -0,0 +1,5 @@
+class A {
+ void foo() {
+ }
+
+<caret>}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java
new file mode 100644
index 000000000000..3284439c1b24
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert-after.java
@@ -0,0 +1,3 @@
+class Foo {
+ int <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java
new file mode 100644
index 000000000000..25766081e3c2
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsert.java
@@ -0,0 +1,4 @@
+class Foo {
+ int
+ <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java
new file mode 100644
index 000000000000..3284439c1b24
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart-after.java
@@ -0,0 +1,3 @@
+class Foo {
+ int <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java
new file mode 100644
index 000000000000..29e2260c35b8
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart.java
@@ -0,0 +1,4 @@
+class Foo {
+ int
+<caret> i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java
new file mode 100644
index 000000000000..3284439c1b24
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2-after.java
@@ -0,0 +1,3 @@
+class Foo {
+ int <caret>i;
+}
diff --git a/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java
new file mode 100644
index 000000000000..6c1bbe85b269
--- /dev/null
+++ b/platform/lang-impl/testData/editor/indentingBackspace/spacingInsertAfterBackspaceAtLineStart2.java
@@ -0,0 +1,4 @@
+class Foo {
+ int
+<caret>i;
+}
diff --git a/platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java b/platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java
new file mode 100644
index 000000000000..f51179dfa5d8
--- /dev/null
+++ b/platform/lang-impl/testSources/com/intellij/codeInsight/editorActions/IndentingBackspaceHandlerUncommittedDocumentTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.codeInsight.editorActions;
+
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+
+import java.io.IOException;
+
+public class IndentingBackspaceHandlerUncommittedDocumentTest extends LightPlatformCodeInsightTestCase {
+ public void testSequentialBackspaceInvocation() throws IOException {
+ configureFromFileText(getTestName(false) + ".java",
+ "class Foo {\n" +
+ "\n" +
+ "\n" +
+ "<caret>}");
+ backspace();
+ backspace();
+ checkResultByText("class Foo {\n" +
+ "<caret>}");
+ }
+
+ public void testMulticaretSequentialBackspaceInvocation() throws IOException {
+ configureFromFileText(getTestName(false) + ".java",
+ "class Foo {\n" +
+ " void m1() {\n" +
+ " \n" +
+ " <caret>}\n" +
+ " void m2() {\n" +
+ " \n" +
+ " <caret>}\n" +
+ "}");
+ backspace();
+ backspace();
+ checkResultByText("class Foo {\n" +
+ " void m1() {<caret>}\n" +
+ " void m2() {<caret>}\n" +
+ "}");
+ }
+} \ No newline at end of file