From 952966d58bbbdf5698ed149828e420dc0ce6d161 Mon Sep 17 00:00:00 2001 From: irengrig Date: Thu, 11 Jun 2015 11:38:37 +0200 Subject: [PATCH 01/86] v8 log processing, allow to read only a part of random-sized-records file --- .../util/CloseableThrowableProcessor.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 platform/util/src/com/intellij/util/CloseableThrowableProcessor.java diff --git a/platform/util/src/com/intellij/util/CloseableThrowableProcessor.java b/platform/util/src/com/intellij/util/CloseableThrowableProcessor.java new file mode 100644 index 000000000000..d15fba49ba6c --- /dev/null +++ b/platform/util/src/com/intellij/util/CloseableThrowableProcessor.java @@ -0,0 +1,25 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util; + +import java.io.Closeable; + +/** + * @author Irina.Chernushina on 6/11/2015. + */ +public interface CloseableThrowableProcessor extends Closeable { + boolean process(S s) throws T; +} From 5f58b442a002480a85f5730a01593c3043345e2b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 11 Jun 2015 22:08:23 +0300 Subject: [PATCH 02/86] single pixel splitter for inspections view --- .../com/intellij/codeInspection/ui/InspectionResultsView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java index f39878760a89..ce0511dcf3d3 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java @@ -130,7 +130,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren myBrowser = new Browser(this); - mySplitter = new Splitter(false, AnalysisUIOptions.getInstance(myProject).SPLITTER_PROPORTION); + mySplitter = new OnePixelSplitter(false, AnalysisUIOptions.getInstance(myProject).SPLITTER_PROPORTION); mySplitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myTree, SideBorder.LEFT | SideBorder.RIGHT)); mySplitter.setSecondComponent(myBrowser); From ce07f3646dbf11c2b2bb8c2a9d9cc1b30404ac9b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 11 Jun 2015 22:23:16 +0300 Subject: [PATCH 03/86] disable field encapsulation for enum constants (IDEA-141305) --- .../EncapsulateFieldsHandler.java | 17 +++++--- .../JavaEncapsulateFieldHelper.java | 12 +++++- .../filterEnumConstants/after/Test.java | 12 ++++++ .../filterEnumConstants/before/Test.java | 4 ++ .../refactoring/EncapsulateFieldsTest.java | 41 +++++++++++-------- 5 files changed, 62 insertions(+), 24 deletions(-) create mode 100644 java/java-tests/testData/refactoring/encapsulateFields/filterEnumConstants/after/Test.java create mode 100644 java/java-tests/testData/refactoring/encapsulateFields/filterEnumConstants/before/Test.java diff --git a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsHandler.java b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsHandler.java index b4b26c1ccc3f..e453744c4f86 100644 --- a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsHandler.java @@ -22,17 +22,17 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiField; -import com.intellij.psi.PsiFile; +import com.intellij.openapi.util.Condition; +import com.intellij.psi.*; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.util.CommonRefactoringUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.HashSet; +import java.util.List; public class EncapsulateFieldsHandler implements RefactoringActionHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.encapsulateFields.EncapsulateFieldsHandler"); @@ -108,8 +108,13 @@ public class EncapsulateFieldsHandler implements RefactoringActionHandler { } LOG.assertTrue(aClass != null); - final PsiField[] fields = aClass.getFields(); - if (fields.length == 0) { + final List fields = ContainerUtil.filter(aClass.getFields(), new Condition() { + @Override + public boolean value(PsiField field) { + return !(field instanceof PsiEnumConstant); + } + }); + if (fields.isEmpty()) { CommonRefactoringUtil.showErrorHint(project, CommonDataKeys.EDITOR.getData(dataContext), "Class has no fields to encapsulate", REFACTORING_NAME, HelpID.ENCAPSULATE_FIELDS); return; diff --git a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/JavaEncapsulateFieldHelper.java b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/JavaEncapsulateFieldHelper.java index 1430a4b98fb7..972824d18d62 100644 --- a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/JavaEncapsulateFieldHelper.java +++ b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/JavaEncapsulateFieldHelper.java @@ -17,6 +17,7 @@ package com.intellij.refactoring.encapsulateFields; import com.intellij.codeInsight.generation.GenerateMembersUtil; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; @@ -25,10 +26,13 @@ import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.VisibilityUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; + /** * @author Max Medvedev */ @@ -307,7 +311,13 @@ public class JavaEncapsulateFieldHelper extends EncapsulateFieldHelper { @NotNull @Override public PsiField[] getApplicableFields(@NotNull PsiClass aClass) { - return aClass.getFields(); + final List fields = ContainerUtil.filter(aClass.getFields(), new Condition() { + @Override + public boolean value(PsiField field) { + return !(field instanceof PsiEnumConstant); + } + }); + return fields.toArray(new PsiField[fields.size()]); } @Override diff --git a/java/java-tests/testData/refactoring/encapsulateFields/filterEnumConstants/after/Test.java b/java/java-tests/testData/refactoring/encapsulateFields/filterEnumConstants/after/Test.java new file mode 100644 index 000000000000..f6d508b6a552 --- /dev/null +++ b/java/java-tests/testData/refactoring/encapsulateFields/filterEnumConstants/after/Test.java @@ -0,0 +1,12 @@ +enum A { + B; + private int i; + + public int getI() { + return i; + } + + public void setI(int i) { + this.i = i; + } +} diff --git a/java/java-tests/testData/refactoring/encapsulateFields/filterEnumConstants/before/Test.java b/java/java-tests/testData/refactoring/encapsulateFields/filterEnumConstants/before/Test.java new file mode 100644 index 000000000000..0b36fa5f5bbd --- /dev/null +++ b/java/java-tests/testData/refactoring/encapsulateFields/filterEnumConstants/before/Test.java @@ -0,0 +1,4 @@ +enum A { + B; + private int i; +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/EncapsulateFieldsTest.java b/java/java-tests/testSrc/com/intellij/refactoring/EncapsulateFieldsTest.java index 329ab69e9d1d..e8634380782b 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/EncapsulateFieldsTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/EncapsulateFieldsTest.java @@ -25,16 +25,11 @@ import com.intellij.codeInsight.generation.GenerateMembersUtil; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiField; import com.intellij.psi.PsiModifier; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.PropertyUtil; -import com.intellij.refactoring.encapsulateFields.EncapsulateFieldsDescriptor; -import com.intellij.refactoring.encapsulateFields.EncapsulateFieldsProcessor; -import com.intellij.refactoring.encapsulateFields.FieldDescriptor; -import com.intellij.refactoring.encapsulateFields.FieldDescriptorImpl; +import com.intellij.refactoring.encapsulateFields.*; import com.intellij.refactoring.util.DocCommentPolicy; import junit.framework.Assert; import org.jetbrains.annotations.NotNull; @@ -82,7 +77,15 @@ public class EncapsulateFieldsTest extends MultiFileTestCase{ assertNotNull("Tested class not found", aClass); final PsiField field = aClass.findFieldByName("i", false); assertNotNull(field); - doTest(aClass, field, null, true, true); + doTest(aClass, null, true, true, field); + }); + } + + public void testFilterEnumConstants() throws Exception { + doTest((rootDir, rootAfter) -> { + final PsiClass aClass = myJavaFacade.findClass("A", GlobalSearchScope.projectScope(myProject)); + assertNotNull("Tested class not found", aClass); + doTest(aClass, null, true, true, new JavaEncapsulateFieldHelper().getApplicableFields(aClass)); }); } @@ -109,28 +112,32 @@ public class EncapsulateFieldsTest extends MultiFileTestCase{ assertNotNull("Tested class not found", aClass); - doTest(aClass, aClass.findFieldByName(fieldName, false), conflicts, true, true); + doTest(aClass, conflicts, true, true, aClass.findFieldByName(fieldName, false)); }); } private static void doTest(final PsiClass aClass, - final PsiField field, final String conflicts, final boolean generateGetters, - final boolean generateSetters) { + final boolean generateSetters, + final PsiField... fields) { try { final Project project = aClass.getProject(); EncapsulateFieldsProcessor processor = new EncapsulateFieldsProcessor(project, new EncapsulateFieldsDescriptor() { @Override public FieldDescriptor[] getSelectedFields() { - return new FieldDescriptor[]{new FieldDescriptorImpl( - field, - GenerateMembersUtil.suggestGetterName(field), - GenerateMembersUtil.suggestSetterName(field), - isToEncapsulateGet() ? GenerateMembersUtil.generateGetterPrototype(field) : null, - isToEncapsulateSet() ? GenerateMembersUtil.generateSetterPrototype(field) : null - )}; + final FieldDescriptor[] descriptors = new FieldDescriptor[fields.length]; + for (int i = 0; i < fields.length; i++) { + descriptors[i] = new FieldDescriptorImpl( + fields[i], + GenerateMembersUtil.suggestGetterName(fields[i]), + GenerateMembersUtil.suggestSetterName(fields[i]), + isToEncapsulateGet() ? GenerateMembersUtil.generateGetterPrototype(fields[i]) : null, + isToEncapsulateSet() ? GenerateMembersUtil.generateSetterPrototype(fields[i]) : null + ); + } + return descriptors; } @Override From 4c5bee489fe2640fb7fc20332d9a2eea5107e72e Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 11 Jun 2015 22:28:59 +0300 Subject: [PATCH 04/86] extract interface: skip enum constants (IDEA-141301) --- .../refactoring/extractInterface/ExtractInterfaceDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceDialog.java b/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceDialog.java index b07cb31c92b0..162f88b294b7 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceDialog.java @@ -51,7 +51,7 @@ class ExtractInterfaceDialog extends JavaExtractSuperBaseDialog { return element.hasModifierProperty(PsiModifier.PUBLIC) && !element.hasModifierProperty(PsiModifier.STATIC); } - else if (element instanceof PsiField) { + else if (element instanceof PsiField && !(element instanceof PsiEnumConstant)) { return element.hasModifierProperty(PsiModifier.FINAL) && element.hasModifierProperty(PsiModifier.STATIC) && element.hasModifierProperty(PsiModifier.PUBLIC); From 16d3c2782ebfdafd13e9c4f0c34607256e20ae1b Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 11 Jun 2015 22:33:14 +0300 Subject: [PATCH 05/86] disable find duplicates on enum constants (IDEA-141298) --- .../refactoring/util/duplicates/MethodDuplicatesHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java b/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java index 78c4ed2ab216..11568aedf84f 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/util/duplicates/MethodDuplicatesHandler.java @@ -108,7 +108,7 @@ public class MethodDuplicatesHandler implements RefactoringActionHandler { } } else if (member instanceof PsiField) { final PsiField field = (PsiField)member; - if (!field.hasInitializer()) { + if (field.getInitializer() == null) { return "Field " + member.getName() + " doesn't have initializer"; } final PsiClass containingClass = field.getContainingClass(); From 1c373eee23781d78c339322af2d63d09f341f9a4 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 11 Jun 2015 22:54:25 +0300 Subject: [PATCH 06/86] disable change class signature for enum (IDEA-141300) --- .../changeSignature/JavaChangeSignatureHandler.java | 2 +- .../refactoring/changeSignatureTarget/disabledForEnum.java | 3 +++ .../com/intellij/refactoring/ChangeSignatureTargetTest.java | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/refactoring/changeSignatureTarget/disabledForEnum.java diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java index 89a123347364..687f7a2a3576 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java @@ -136,7 +136,7 @@ public class JavaChangeSignatureHandler implements ChangeSignatureHandler { return elementParent; } if (elementParent instanceof PsiClass && ((PsiClass)elementParent).getNameIdentifier()==element) { - if (((PsiClass)elementParent).isAnnotationType()) { + if (((PsiClass)elementParent).isAnnotationType() || ((PsiClass)elementParent).isEnum()) { return null; } return elementParent; diff --git a/java/java-tests/testData/refactoring/changeSignatureTarget/disabledForEnum.java b/java/java-tests/testData/refactoring/changeSignatureTarget/disabledForEnum.java new file mode 100644 index 000000000000..2245a8a54298 --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignatureTarget/disabledForEnum.java @@ -0,0 +1,3 @@ +enum E { + ; +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java index 9a860f98a786..5391cec1f45a 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTargetTest.java @@ -51,6 +51,11 @@ public class ChangeSignatureTargetTest extends LightCodeInsightTestCase { doTest("A1"); } + public void testDisabledForEnum() throws Exception { + configureByFile("/refactoring/changeSignatureTarget/" + getTestName(true) + ".java"); + assertNull(new JavaChangeSignatureHandler().findTargetMember(getFile(), getEditor())); + } + private void doTest(String expectedMemberName) throws Exception { String basePath = "/refactoring/changeSignatureTarget/" + getTestName(true); @NonNls final String filePath = basePath + ".java"; From 38e2d2cd6c8aba6f895027e56a9da3105ac3438c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 11 Jun 2015 23:24:33 +0300 Subject: [PATCH 07/86] disable replace constructor with builder/factory for enums (IDEA-141299) --- .../ReplaceConstructorWithBuilderAction.java | 2 +- .../ReplaceConstructorWithFactoryAction.java | 23 ++++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/actions/ReplaceConstructorWithBuilderAction.java b/java/java-impl/src/com/intellij/refactoring/actions/ReplaceConstructorWithBuilderAction.java index 0775c65258a8..b71b01bef480 100644 --- a/java/java-impl/src/com/intellij/refactoring/actions/ReplaceConstructorWithBuilderAction.java +++ b/java/java-impl/src/com/intellij/refactoring/actions/ReplaceConstructorWithBuilderAction.java @@ -39,7 +39,7 @@ public class ReplaceConstructorWithBuilderAction extends BaseRefactoringAction{ final int offset = editor.getCaretModel().getOffset(); final PsiElement elementAt = file.findElementAt(offset); final PsiClass psiClass = ReplaceConstructorWithBuilderHandler.getParentNamedClass(elementAt); - return psiClass != null && psiClass.getConstructors().length > 0; + return psiClass != null && psiClass.getConstructors().length > 0 && !psiClass.isEnum(); } protected boolean isEnabledOnElements(@NotNull final PsiElement[] elements) { diff --git a/java/java-impl/src/com/intellij/refactoring/actions/ReplaceConstructorWithFactoryAction.java b/java/java-impl/src/com/intellij/refactoring/actions/ReplaceConstructorWithFactoryAction.java index 1d32d0ee5183..a464fad6902a 100644 --- a/java/java-impl/src/com/intellij/refactoring/actions/ReplaceConstructorWithFactoryAction.java +++ b/java/java-impl/src/com/intellij/refactoring/actions/ReplaceConstructorWithFactoryAction.java @@ -17,8 +17,10 @@ package com.intellij.refactoring.actions; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiMethod; import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.replaceConstructorWithFactory.ReplaceConstructorWithFactoryHandler; @@ -32,10 +34,25 @@ public class ReplaceConstructorWithFactoryAction extends BaseRefactoringAction { return false; } + @Override protected boolean isEnabledOnElements(@NotNull PsiElement[] elements) { - return elements.length == 1 && - (elements[0] instanceof PsiMethod && ((PsiMethod)elements[0]).isConstructor() || elements[0] instanceof PsiClass) - && elements[0].getLanguage().isKindOf(JavaLanguage.INSTANCE); + return false; + } + + @Override + protected boolean isAvailableOnElementInEditorAndFile(@NotNull PsiElement element, + @NotNull Editor editor, + @NotNull PsiFile file, + @NotNull DataContext context) { + return (element instanceof PsiMethod && + ((PsiMethod)element).isConstructor() && + acceptClass(((PsiMethod)element).getContainingClass()) || + acceptClass(element)) + && element.getLanguage().isKindOf(JavaLanguage.INSTANCE); + } + + private static boolean acceptClass(PsiElement element) { + return element instanceof PsiClass && !((PsiClass)element).isEnum(); } protected RefactoringActionHandler getHandler(@NotNull DataContext dataContext) { From 67f2cdca5fdeaccd83deaece7625e797e89b60e8 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 11 Jun 2015 23:30:43 +0300 Subject: [PATCH 08/86] separate actions in tests secondary group --- .../execution/testframework/ToolbarPanel.java | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java b/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java index 7bd1aec865bb..56502b99c51d 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/ToolbarPanel.java @@ -123,22 +123,26 @@ public class ToolbarPanel extends JPanel implements OccurenceNavigator, Disposab null, properties, TestConsoleProperties.TRACK_RUNNING_TEST)); secondaryGroup.add(new ToggleBooleanProperty("Hide Ignored", null, null, properties, TestConsoleProperties.HIDE_IGNORED_TEST)); - secondaryGroup.add(new ToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.select.first.failed.action.name"), - null, null, properties, TestConsoleProperties.SELECT_FIRST_DEFECT)); - secondaryGroup.add(new ToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.scroll.to.stacktrace.action.name"), - ExecutionBundle.message("junit.runing.info.scroll.to.stacktrace.action.description"), - null, properties, TestConsoleProperties.SCROLL_TO_STACK_TRACE)); - myScrollToSource = new ScrollToTestSourceAction(properties); - secondaryGroup.add(myScrollToSource); - secondaryGroup.add(new ToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.open.source.at.exception.action.name"), - ExecutionBundle.message("junit.runing.info.open.source.at.exception.action.description"), - null, properties, TestConsoleProperties.OPEN_FAILURE_LINE)); if (Registry.is("tests.view.old.statistics.panel")) { secondaryGroup.add(new ShowStatisticsAction(properties)); } secondaryGroup.add(new ToggleBooleanProperty("Show Inline Statistics", "Toggle the visibility of the test duration in the tree", null, properties, TestConsoleProperties.SHOW_INLINE_STATISTICS)); + + secondaryGroup.addSeparator(); + secondaryGroup.add(new ToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.scroll.to.stacktrace.action.name"), + ExecutionBundle.message("junit.runing.info.scroll.to.stacktrace.action.description"), + null, properties, TestConsoleProperties.SCROLL_TO_STACK_TRACE)); + secondaryGroup.add(new ToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.open.source.at.exception.action.name"), + ExecutionBundle.message("junit.runing.info.open.source.at.exception.action.description"), + null, properties, TestConsoleProperties.OPEN_FAILURE_LINE)); + myScrollToSource = new ScrollToTestSourceAction(properties); + secondaryGroup.add(myScrollToSource); + secondaryGroup.add(new AdjustAutotestDelayActionGroup(parent)); + secondaryGroup.addSeparator(); + secondaryGroup.add(new ToggleBooleanProperty(ExecutionBundle.message("junit.runing.info.select.first.failed.action.name"), + null, null, properties, TestConsoleProperties.SELECT_FIRST_DEFECT)); properties.appendAdditionalActions(secondaryGroup, environment, parent); actionGroup.add(secondaryGroup); From 18182a6ba7cc9ae055acfde514c6951e386d06fe Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 12 Jun 2015 02:58:25 +0200 Subject: [PATCH 09/86] +loadIcon(path) method --- .../src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java index eaa05f15b711..1f729b7d1ae3 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/DarculaLaf.java @@ -437,4 +437,8 @@ public class DarculaLaf extends BasicLookAndFeel { public boolean getSupportsWindowDecorations() { return true; } + + public static Icon loadIcon(String path) { + return IconLoader.findIcon(path, DarculaLaf.class, true); + } } From c5676426f7fd1b0a3592ee8915405c6c1b20ece5 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 12 Jun 2015 02:59:56 +0200 Subject: [PATCH 10/86] combobox arrow buttons for yosemite --- .../intellij/ide/ui/laf/icons/comboboxMac.png | Bin 0 -> 1825 bytes .../intellij/ide/ui/laf/icons/comboboxMac@2x.png | Bin 0 -> 2745 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxMac.png create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxMac@2x.png diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxMac.png b/platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxMac.png new file mode 100644 index 0000000000000000000000000000000000000000..868e624dc27c2cb1149521af4f7ad328c73f9bac GIT binary patch literal 1825 zcmaJ?do)ye9G}USM_3$GBGXtx%)K*=X(ofrP~#YB2p!=H8L(l_w}K9t9c}W5+6a3e=vP`5KGr6(VSrkS0!#*|D{0(OEdGC2rShvcPDtQy z`Ti#{9-fTCfCR>oL`+5wF3v$03grnfSV|yRID)Jl?_y{?LLhiNg3<(n(XP>)#Zs9< zr8{&PMTx~ckqRfIDj6&i^64ZGL!p3pY_>lb$YioW&O9cQ8Nl}U3}6K?7jW70JlI@N z;4zLBBCgu-@gq`0y6so-lEzp0!zxnq7%A>0okh0fo!KE0E(llOBf?i|moByZJmmB2 zMq(LW-bCDPKI|#kvZ(ul-(`DknvJ2LzojPXyeB{PxFtfE;#L5K67DLqk}-td1;_oer>c*NV3M2;eB1fcyE3L51pI~B{R>~ z#npIJRmL(h-0m##wp~@*+0mzt0YBWB?aA2sfBCauBD5XF#f{=!>52U-jCcG+xoj5uT*ZK22Moz%BpmQeW=^e(R0edJ7#KJtr) z`m>?iBj@ z)mv46@nQG*DNgTurk#w;vQ6gORL-EM=dioqdV_&CZ10tYx=z}{*!+ZFXYuzdtL>9| z&U~tgkIqL(3a$oy>g*qcz{+94%Vn$FCkyKx?w3dV z{ux|ox+is@WWa5MJTj`qG_ND6_(4QemmftS3>+;bCc+KMdW@pUJ qF0pUTuc>e8>mINJ-+lW1@uY9{-J-L?Yy}7e z((&{l1}IM(SO7|tM& z>N*xB7zif&;AlJ!oVpYP7jyVZGzjGEBIZ+RYz6>{WJIyJc<6XzGZez2=3hkoM4Dep^e1QhZq1YqN# z{}dHW-U@N!2^bIzd;^SzL^(k=V&N#vhK<;b4iL1`Mj$sK&`1~(i^DkLkZ8!~530;2 zpfhm+MAGM6N(&E-1^_+|fe?vAaFHXNCx}9zuvjbtiAJE&Fl7Wx7|R8yVi;Fw{e^+Z z5YhxJKEUE}Axn(ZNZwum4^>wBPYWFWS6Z&{^O%$aLx`z-1PYE^YUxWLnf(7lIh?Q2 zLLh+gZ@vGMSV)QGGY|m`A#bmMrd%A;dMOnj=O$oK0iJ-uoClr~C^W+KvDwoFaB;uh;9yp6d$6+w8ND>O^j@-Bjg+jSwT%Fv} z?kEBlv&j*IMY=hD!4i42y&MJ?_=2VXizR&%yCet>UzwT65U}&jVFMi z(#4n5bAH7|0{0D(+Fob7EBgBS61}@&u_FD%od*(06J{A;tVUopI4O2`B8N5nXxsNI zrk+K)ZNJWRRk^1CnM9u{gITg&v{v8WP712*CDIsUuH{zK+kTP~JC^AhpQBh>><&IR z(Gb4gc@%WQ)-lve`^jsG;neQMr!g^>zDb93nY8o~iF%hO-JvQX3A9~xHbTFxb~*Jn`*P>utUH#|5BdH0Iv*R11oa!#t%F6##AtVHBszWO#jb{I9jmsASo*3A?WeDbpz~(6Ug;eUo69P_!19UWm79bkvR?Ry z+uf+2sRp$^**#&UZfx5D>B>WERIUTri=8UDiPb}_%Y=HPg$~H|7Sj)}dXZL0LEEe3 zd({j5~yR*Xv_(EAu8|J)L-^((Ql<0p@mOQIGQ?`hNl+ZSib)r z>=y1j&5myN=pONuRpsSV@3Lxc%9ok$zr`XQtd%>Km-N5cY!V&T|M8?1DwZILGksS+b2P5gYi9CS^lOb zeNH3jvwgDe8HkKMXR}|pYRIGb&^fN%%O3kCX#(FPPJ(W^mziz(JmvSWQ!+zZepGi- z$!hTf%4;k08L$57f|7*~^|-5t&hap=c2~?a-ws)Yh->OMXj+w^P+owq9@S7P{_B`c z=ak&BV8+`}#V9<`HE3O>WDE(+`VI3BXhi&N;C*USR(ryQ`5IYT`J~<@7&xfEF3;RD z6l1SZo1OfA-el^4d?BN4Uy^-Od~Uk?tF)8VGYA7Q-B#-)Rc>fJxs7rJPtSkEjhMi3 z{#dwQFFki6oKQF2NjM)Z$!o9hEiqP;G@Nc{XOBlP(S7fISBDUif?hw9b1j;UYz;CN zyhSG_6?3Zc_TGds4u?|(XcwEG7Ou~jq=eFS2IygfE*INY<;;3!k~Yv|!1?gs3*3Ov zs2{@{f4h^z)Fr>s-rM(^bX|Gmu01VBWEBZ7Js#>+C;t9(+J>?h$3l(=pZVc!gRCiZ zGsf>#Wj>~tdAhE9MGyHz$W6}CKgXC=aTnDrBadksw@gyZ0^*OPhT7)w{AihIY;#xs zLrQS5fhk7yW6O8`S@tjmB$@Lu$C+Y%{`Q5v1%V3JUNdHdg8Z&3Wz~#is3ya(yi_=q zNvdAC&zJVzNo^4CpH#J({P=CtaNX*FXJ(hyO8fm$LGR`@eMF+WPq_K@#}7(X!cjfy zzdDjf`!qG4m!jBq?ex4WnIp;T-R|$-7K9Yx)T&==7W^PmFS`^WC+uL3C6p6VM0Zp1 zaC67IgF4Mys;q(r!us1cWuS=tBdUtjmWVNDd&=6h16L-vf1`Fn%VhfzLGPyv38y#C zs5VU>9)lX>L?Eqrlff1-uUkKMHkW`rXyrPBzr;S(aLqZc*5GMLUgCoh z)n8KX++9l({ZUxv{Ys~IR|GA52QYZ}{55>DQOQ|ZL@#;S!V|)w>2PX(YY2*G{2cF} zTd`9(zUUl5=qg#W=LW`oDi5I#?=$_aNVVqqmNnY%=r60Y(43vZUGCIy(rBlDp6)WH zmd(+scDST-7H1gwSl0*lC(&BNYRBC5)d?m+@j~+-$D`lV0fTMKv4m;Xk)7&%0fuKLKATMXc?{8AJz zm~Q%5iRjfYH@r#0xQD=6)4Gd`q|)+&qdsoS@- zPuf_gUsOJHHqRl4#^T`)FPc-!U`ZzB`mu>^;km?97HMxd9W<>A2^V4+LhfRX$4_zo zJ)_ZAYfZEcdl?)i&enC^X^YR4mOj|NH^Tz|fdcK6UtF9h7Vc9WI#u&)d==Xwc_zk1 zRv4#ieAg_=bC?7_Pg#%GX=-e2M9d9JXZ(cGF)=EJPYukjI*r?XFe)r`jum`l7&BWm l-OGxXo8RpC-epk(399g@utV0}-m~ Date: Fri, 12 Jun 2015 03:00:33 +0200 Subject: [PATCH 11/86] yosemite combobox resources --- .../intellij/ide/ui/laf/icons/comboboxLeft.png | Bin 0 -> 1070 bytes .../ide/ui/laf/icons/comboboxLeft@2x.png | Bin 0 -> 1202 bytes .../ide/ui/laf/icons/comboboxTopBottom.png | Bin 0 -> 1044 bytes .../ide/ui/laf/icons/comboboxTopBottom@2x.png | Bin 0 -> 1047 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxLeft.png create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxLeft@2x.png create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxTopBottom.png create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxTopBottom@2x.png diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxLeft.png b/platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..7398d6ba8257014a6dc0cf2766b61173d3bb89fc GIT binary patch literal 1070 zcmaJ=O-K|`93L!0Oi4PJAD3x7q~Xq&t~!&O?e46((uk}}ZIaM9^LBU8nK#Y6ZAUS} zphHN9NTtZg4pAXVhp3=1%r4O-q)Qz_=o2~!T{;-lo7LSqv<57=Z07xNSW7Kp+H$dfhMSS+I8H&ugppgKznN&jVC&SPN zq@Ql{sVvt@whJ`pZ)+FYn@Jwq4BNr*tdA8$e~ZZSq(hVR7?oj|K>-S9x>>`y}koiwz_a5&dBvQbu4-SjS-awu6Aqo#utQw32eKw%zQ*ENw7_*N;% zb+hdumg6G+P-}#ba6!S}(c%}_a7!L5K{aCl6Xmg50n4*Rv7R6d3rCiKt)B*3w+#(4 zSGcGb&qXTAw}sV;=E6maVi}wa<6B7$R zZay@Y2Y0^T*cM9HhupR4-5p=(nhy=PP$`kE3eC;LnwZsV{U4{7YU@K~KUZJW-0po| z@yq9|41V4})mx{|Ix~xNPUEhLLxbNgPJf?$wO*q#Z!<&3?`nZLlXsaOFctV zGjmIG9R(vGU*Et&-^f7Mz|zXp*vi020Sc6WwiTtMSp~VcLG1$aY?U%fN(!v>^~=l4 z^~#O)@{7{-4J|D#^$m>ljf`}GDs+o0^GXscbn}XpVJ5hw7AF^F7L;V>=P7_pOiaoz zEwNPsx)kDt+yc06!V;*iRM zRQ;gT;{4L0WMIUlDTAykuyQU+O)SYT3dzsUfrVl~Mt(_taYlZDg0nL?)D$#)6O%LZ zK!TcJUB13no_WP3iFwJXo-VdZKy&mmGgGWgO`Qzf3=Pc;%q|ZfO-urjZ9n|4V?|loeZ$*1to~w0-((H{644~kx-=!OXa(-4RWPrN`5Jo%^Q0n>aD zFmW@!`C7riz^LHq;uunK>&;Z}tQH3m*ZAxY-HVtt!!JgmhQ02DtMncOYO$u>F(``5|a`o;{MOlaX9~Z%_bfDS<5WT zW7$R8B<&umbtz4H{!{g|k+%TL1ry$qSoXfh)A~3>T@wYJ4w#%h?!0SV_RVd!Klj{&Z+-vHmW&nqF4t8qK7DAOD>U4ouJFKWomhLjv`G%rcMbet2!}|HCy^! z(B9vg()+u0(V!ZSkqy3t2`qp#(zkkSPx56d&nw|`aLrI;-UW5b)JjrmwT+BH7mxy7 z7t&d-mW+rrC)7p6$WfBVHpA94JR4#~NeD|UPZmB3M{|vglvJ7vv9KjmS%e&kVRE?~ zoeR^@?P54l6d9Ihcs_(ZLSCPZG(Ti}RYe8`c)Dvk$b>c-FlwE!7s(XPbfpB#S*5kT zLYr{I7+-T3j%I_BijJ!Ke^<*|_4ZH_tmV5dv6t#|0FwkB>~(cKxJ*?L%8_C&&=7P} z5cU+i*p`I|dRgd@u~@!qWR0rnrX5@!&ZAUSO4uIKY#k&NnZi7@X&O>otZ$ABEYC)o zSdNPeO|@}8&P7F`J}iiAEL_AYQ17*Xjfz-f4IADN8wkR3aAXCz<~d+AyU-%@g-hl- zxo{$1t3-KWL%ssmSSObPwr)c#gOg!`@%}UJ;uY3Va9kBHHdf^iY^-?~i`)A3dKf>9 zp@b4m`R~8I<;n)xZCe(mN;X$Aua5ZPuKS<9OO?`0>GqM#&z+zDT-D^0bGIs~BeVKUqV(3uycy{vL$GPKAZ$61lzws9@EcU?3k?QfU yqYtNNmu^*^H?AHemiNz0jXij*RZNV|FYW3eel(KTuZ#}E;GHJot;)Toj-kJq-d9Ed literal 0 HcmV?d00001 diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxTopBottom@2x.png b/platform/platform-impl/src/com/intellij/ide/ui/laf/icons/comboboxTopBottom@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b2478426c5d428729052a7cf134318967edcfeae GIT binary patch literal 1047 zcmaJ=O=#0l91ngo?bL%q1;;Z(nXu-o&DzA(t!*+_G;?%?6%S&TytScAUQFI>Rz%dH z;6?D}L1ZB8Fhm%58%(_jUSuZ^qIerl#0efeh~P`tb~{+ZKkwtu|M&ZUzWZaN=OZ1* zJ1B~ZkYsh8O!2QlbwCN>AU_FRBeovD@fxh8cF1C;ZLPmWO&EOPGBHc{Ec3ZTL-zXC) z7#rv=%QIYmAEo&d=;a0r=B=!rlE@bo2M>C#58aLGwx^m^L2X&0R0z%Wx zDvp&AMt&K&Ae*gM4fJZdVL74lOdX|Za?bIw?ietqq-es!Se7ZPQgT=oxipu^a6GSy znYb#bd|DEdF;U{Ou_jhQ#*7Ue+{Bt&*i2h&I1si=JS)(%u0wO!LpG=acv!G~`j`N%8o zfckpj#`2K~*NpGIu<$VRrTg>Tk4x_!E&W=-H=izc$KtoHRHXIJ)hFM(Kb@wct2 Date: Fri, 12 Jun 2015 03:01:25 +0200 Subject: [PATCH 12/86] refactor: use unified loadIcon method --- .../laf/intellij/MacIntelliJCheckBoxUI.java | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJCheckBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJCheckBoxUI.java index db7cbcd21d36..077a788f0e79 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJCheckBoxUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJCheckBoxUI.java @@ -15,7 +15,7 @@ */ package com.intellij.ide.ui.laf.intellij; -import com.intellij.openapi.util.IconLoader; +import com.intellij.ide.ui.laf.darcula.DarculaLaf; import com.intellij.util.ui.EmptyIcon; import javax.swing.*; @@ -27,6 +27,8 @@ import java.awt.*; */ public class MacIntelliJCheckBoxUI extends IntelliJCheckBoxUI { public static final Icon DEFAULT_ICON = EmptyIcon.create(14); + public static final Icon CHECKED_ICON = DarculaLaf.loadIcon("/com/intellij/ide/ui/laf/icons/checkboxSelectedMac.png"); + public static final Icon UNCHECKED_ICON = DarculaLaf.loadIcon("/com/intellij/ide/ui/laf/icons/checkboxMac.png"); @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"}) public static ComponentUI createUI(JComponent c) { @@ -35,23 +37,15 @@ public class MacIntelliJCheckBoxUI extends IntelliJCheckBoxUI { @Override protected void drawCheckIcon(JComponent c, Graphics2D g, JCheckBox b, Rectangle iconRect, boolean selected, boolean enabled) { - Icon icon; - if (selected) { - icon = IconLoader.findIcon("/com/intellij/ide/ui/laf/icons/checkboxSelectedMac.png", MacIntelliJCheckBoxUI.class, true); - } else { - icon = IconLoader.findIcon("/com/intellij/ide/ui/laf/icons/checkboxMac.png", MacIntelliJCheckBoxUI.class, true); - } - if (icon != null) { - icon.paintIcon(c, g, iconRect.x, iconRect.y); - } + getIcon(selected).paintIcon(c, g, iconRect.x, iconRect.y); + } + + private Icon getIcon(boolean selected) { + return selected ? CHECKED_ICON : UNCHECKED_ICON; } @Override public Icon getDefaultIcon() { return DEFAULT_ICON; } - - private static boolean isGraphite() { - return false; - } } From 993340662c1602b2ccce6d2f62ec200af878f8ae Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 12 Jun 2015 03:02:26 +0200 Subject: [PATCH 13/86] new Yosemite ComboBox --- .../laf/intellij/MacIntelliJComboBoxUI.java | 284 ++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java new file mode 100644 index 000000000000..4a48ffdcfe82 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java @@ -0,0 +1,284 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ide.ui.laf.intellij; + +import com.intellij.ide.ui.laf.darcula.DarculaLaf; +import com.intellij.openapi.util.IconLoader; +import com.intellij.util.ui.JBUI; + +import javax.swing.*; +import javax.swing.border.Border; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicArrowButton; +import javax.swing.plaf.basic.BasicComboBoxEditor; +import javax.swing.plaf.basic.BasicComboBoxUI; +import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +/** + * @author Konstantin Bulenkov + */ +public class MacIntelliJComboBoxUI extends BasicComboBoxUI implements Border, UIResource { + private static final Icon COMBOBOX = DarculaLaf.loadIcon("/com/intellij/ide/ui/laf/icons/comboboxMac.png"); + private static final Icon COMBOBOX_LEFT = DarculaLaf.loadIcon("/com/intellij/ide/ui/laf/icons/comboboxLeft.png"); + private static final Icon COMBOBOX_TOP_BOTTOM = DarculaLaf.loadIcon("/com/intellij/ide/ui/laf/icons/comboboxTopBottom.png"); + private final JComboBox myComboBox; + + public MacIntelliJComboBoxUI(JComboBox comboBox) { + myComboBox = comboBox; + myComboBox.setBorder(this); + currentValuePane = new CellRendererPane() { + @Override + public void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h, boolean shouldValidate) { + c.setBackground(Color.WHITE); + super.paintComponent(g, c, p, x, y, w, h, shouldValidate); + } + }; + } + + @SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"}) + public static ComponentUI createUI(JComponent c) { + return new MacIntelliJComboBoxUI((JComboBox)c); + } + + @Override + protected JButton createArrowButton() { + final Color bg = myComboBox.getBackground(); + final Color fg = myComboBox.getForeground(); + JButton button = new BasicArrowButton(SwingConstants.SOUTH, bg, fg, fg, fg) { + + @Override + public void paint(Graphics g2) { + Icon icon = myComboBox.isEnabled() ? COMBOBOX : IconLoader.getDisabledIcon(COMBOBOX); + icon.paintIcon(this, g2, 0, 0); + } + + @Override + public Dimension getPreferredSize() { + return JBUI.size(COMBOBOX.getIconWidth(), COMBOBOX.getIconWidth()); + } + }; + button.setBorder(BorderFactory.createEmptyBorder()); + button.setOpaque(false); + return button; + } + + @Override + public Dimension getMinimumSize(JComponent c) { + return getSizeWithIcon(super.getMinimumSize(c)); + } + + private Dimension getSizeWithIcon(Dimension d) { + Insets insets = getBorderInsets(myComboBox); + return new Dimension(Math.max(d.width + insets.left + insets.right, COMBOBOX.getIconWidth()), Math.max(d.height, + COMBOBOX.getIconHeight())); + } + + @Override + public Dimension getPreferredSize(JComponent c) { + return getSizeWithIcon(super.getPreferredSize(c)); + } + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + + } + + @Override + protected ComboBoxEditor createEditor() { + final ComboBoxEditor comboBoxEditor = new BasicComboBoxEditor.UIResource() { + @Override + protected JTextField createEditorComponent() { + return new JTextField() { + { + setOpaque(false); + setBorder(new Border() { + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + } + + @Override + public Insets getBorderInsets(Component c) { + return JBUI.insets(2, 6, 2, 6); + } + + @Override + public boolean isBorderOpaque() { + return false; + } + }); + } + + public void setText(String s) { + if (getText().equals(s)) { + return; + } + super.setText(s); + } + + public void setBorder(Border b) { + super.setBorder(b); + } + + @Override + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + return new Dimension(size.width, COMBOBOX.getIconHeight() - 2); + } + }; + } + }; + if (comboBoxEditor.getEditorComponent() != null) { + comboBoxEditor.getEditorComponent().addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + process(e); + } + + @Override + public void keyReleased(KeyEvent e) { + process(e); + } + + private void process(KeyEvent e) { + final int code = e.getKeyCode(); + if ((code == KeyEvent.VK_UP || code == KeyEvent.VK_DOWN) && e.getModifiers() == 0) { + comboBox.dispatchEvent(e); + } + } + }); + comboBoxEditor.getEditorComponent().addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + update(); + } + + @Override + public void focusLost(FocusEvent e) { + update(); + } + + void update() { + if (comboBox != null) { + comboBox.revalidate(); + comboBox.repaint(); + } + } + }); + } + return comboBoxEditor; + } + + @Override + protected Rectangle rectangleForCurrentValue() { + Rectangle rect = super.rectangleForCurrentValue(); + rect.y+=2; + rect.x+=5; + rect.height-=4; + return rect; + } + + @Override + public Insets getBorderInsets(Component c) { + return JBUI.insets(0, 5, 0, 0); + } + + @Override + protected LayoutManager createLayoutManager() { + return new LayoutManager() { + @Override + public void addLayoutComponent(String name, Component comp) { + + } + + @Override + public void removeLayoutComponent(Component comp) { + + } + + @Override + public Dimension preferredLayoutSize(Container parent) { + return null; + } + + @Override + public Dimension minimumLayoutSize(Container parent) { + return null; + } + + @Override + public void layoutContainer(Container parent) { + JComboBox cb = (JComboBox)parent; + int width = cb.getWidth(); + int height = cb.getHeight(); + + Insets insets = getInsets(); + int buttonHeight = height - (insets.top + insets.bottom); + int buttonWidth = buttonHeight; + if (arrowButton != null) { + Insets arrowInsets = arrowButton.getInsets(); + buttonWidth = arrowButton.getPreferredSize().width + arrowInsets.left + arrowInsets.right; + } + Rectangle cvb; + + if (arrowButton != null) { + arrowButton.setBounds(width - (insets.right + buttonWidth), + insets.top, buttonWidth, buttonHeight); + } + if ( editor != null ) { + cvb = rectangleForCurrentValue(); + editor.setBounds(cvb); + } + + } + }; + } + + @Override + public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) { + g.setColor(Color.WHITE); + g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); + } + + + @Override + public void paint(Graphics g, JComponent c) { + super.paint(g, c); + + int stop = arrowButton.getBounds().x; + g.setClip(0,0, stop, COMBOBOX.getIconHeight()); + COMBOBOX_LEFT.paintIcon(c,g,0,0); + int x = COMBOBOX_LEFT.getIconWidth(); + while (x < stop) { + COMBOBOX_TOP_BOTTOM.paintIcon(c, g, x, 0); + x+=COMBOBOX_TOP_BOTTOM.getIconWidth(); + } + ((Graphics2D)g).scale(0.5d, 0.5d); + g.setColor(Color.WHITE); + g.drawLine(COMBOBOX_LEFT.getIconWidth() * 2, 3, stop * 2, 3); + g.drawLine(COMBOBOX_LEFT.getIconWidth() * 2, 40, stop * 2, 40); + ((Graphics2D)g).scale(2d, 2d); + } + + @Override + public boolean isBorderOpaque() { + return false; + } +} From a4929ccc9243fc3fbeb34312ff6a083aa410c52d Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 12 Jun 2015 03:03:12 +0200 Subject: [PATCH 14/86] register comboboxui for IntelliJ laf on mac --- .../src/com/intellij/ide/ui/laf/intellijlaf_mac.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties index 63c3c43f8653..a193b504a3f4 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties @@ -8,5 +8,7 @@ PopupMenu.translucentBackground=ececec Spinner.background=ececec Spinner.darcula.disabledButtonColor=ececec +ComboBoxUI=com.intellij.ide.ui.laf.intellij.MacIntelliJComboBoxUI + SplitPane.highlight=ececec From 6e77f33f9d0e033c7626848b28ee699fa36c6953 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Fri, 12 Jun 2015 03:32:21 +0200 Subject: [PATCH 15/86] + isGraphite() --- .../src/com/intellij/ide/ui/laf/IntelliJLaf.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java index 07f6726ce928..363e46d03ffa 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java @@ -56,5 +56,11 @@ public class IntelliJLaf extends DarculaLaf { defaults.put("Label.font", font); defaults.put("CheckBox.font", font); defaults.put("RadioButton.font", font); + defaults.put("ComboBox.font", font); + } + + public static boolean isGraphite() { + Color c = UIManager.getColor("controlHighlight"); + return c != null && c.getBlue() < 150; } } From 26946ae9acc76b9f776c7b776609ed6c65fa490a Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Fri, 12 Jun 2015 07:15:01 +0300 Subject: [PATCH 16/86] add Duplicate shortcut-set --- .../com/intellij/openapi/actionSystem/CommonShortcuts.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/CommonShortcuts.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/CommonShortcuts.java index 5a3063d631fb..6bebdd091055 100644 --- a/platform/platform-api/src/com/intellij/openapi/actionSystem/CommonShortcuts.java +++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/CommonShortcuts.java @@ -96,11 +96,14 @@ public class CommonShortcuts { return shortcutsById(IdeActions.ACTION_NEW_ELEMENT); } + public static ShortcutSet getDuplicate() { + return shortcutsById(IdeActions.ACTION_EDITOR_DUPLICATE); + } + public static ShortcutSet getMove() { return shortcutsById(IdeActions.ACTION_MOVE); } - public static ShortcutSet getRename() { return shortcutsById(IdeActions.ACTION_RENAME); } From 5ad3c32c70d86e61675eb53a8f696e714c7928aa Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Fri, 12 Jun 2015 09:46:29 +0300 Subject: [PATCH 17/86] Fix missing dark line at the bottom --- .../src/com/intellij/util/ui/MacUIUtil.java | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/MacUIUtil.java b/platform/util/src/com/intellij/util/ui/MacUIUtil.java index af3b55023539..b5899bc95c46 100644 --- a/platform/util/src/com/intellij/util/ui/MacUIUtil.java +++ b/platform/util/src/com/intellij/util/ui/MacUIUtil.java @@ -136,27 +136,16 @@ public class MacUIUtil { g.setColor(c.getBackground()); g.fillRect(x1, y1, width1, height1); - + if (!myEnabledComponent.isEnabled()) { ((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f)); } g.setColor(new Color(100, 100, 100, 200)); - g.drawLine(x1, y1, x1 + width1 - 1, y1); - - g.setColor(new Color(212, 212, 212, 200)); - g.drawLine(x1, y1 + 1, x1 + width1 - 1, y1 + 1); + g.drawRect(x1, y1, width1 - 1, height1 - 1); g.setColor(Gray._225); - g.drawLine(x1 + 1, y1 + height1 - 1, x1 + width1 - 2, y1 + height1 - 1); - - g.setColor(new Color(30, 30, 30, 70)); - g.drawLine(x1, y1, x1, y1 + height1 - 1); - g.drawLine(x1 + width1 - 1, y1, x1 + width1 - 1, y1 + height1 - 1); - - g.setColor(new Color(30, 30, 30, 10)); - g.drawLine(x1 + 1, y1, x1 + 1, y1 + height1 - 1); - g.drawLine(x1 + width1 - 2, y1, x1 + width1 - 2, y1 + height1 - 1); + g.drawRect(x1 + 1, y1 + 1, width1 - 3, height1 - 3); if (myEnabledComponent.isEnabled() && myEnabledComponent.isVisible() && hasFocus(myEnabledComponent)) { paintTextFieldFocusRing((Graphics2D) g, new Rectangle(x1, y1, width1, height1)); From 7384bace1d32cda3a2029ae61c0f9963f296c06e Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 12 Jun 2015 10:28:17 +0200 Subject: [PATCH 18/86] commented paths to license files (the files were removed because of IDEA-141315) --- build/conf/nsis/paths.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/conf/nsis/paths.nsi b/build/conf/nsis/paths.nsi index 0e9299aaffba..c9e28527f1ea 100644 --- a/build/conf/nsis/paths.nsi +++ b/build/conf/nsis/paths.nsi @@ -1,6 +1,6 @@ ; Installer images !define IMAGES_LOCATION "${BASE_DIR}\build\images\idea" -!define LICENSE_FILE "${BASE_DIR}\license\IDEA_license" +;!define LICENSE_FILE "${BASE_DIR}\license\IDEA_license" !define PRODUCT_PROPERTIES_FILE "${BASE_DIR}\out\release\dist.all\bin\idea.properties" !define PRODUCT_VM_OPTIONS_NAME idea*.exe.vmoptions !define PRODUCT_VM_OPTIONS_FILE "${BASE_DIR}\out\release\dist.win\bin\${PRODUCT_VM_OPTIONS_NAME}" \ No newline at end of file From 7d2bbf0473994ae22e856e6f04711fe8eac5c7c1 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 12 Jun 2015 11:57:44 +0300 Subject: [PATCH 19/86] fixed test for windows --- .../com/intellij/execution/process/ProcessWaitForTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/util/testSrc/com/intellij/execution/process/ProcessWaitForTest.java b/platform/util/testSrc/com/intellij/execution/process/ProcessWaitForTest.java index 4042b0b450b4..d596bce075e9 100644 --- a/platform/util/testSrc/com/intellij/execution/process/ProcessWaitForTest.java +++ b/platform/util/testSrc/com/intellij/execution/process/ProcessWaitForTest.java @@ -15,6 +15,7 @@ */ package com.intellij.execution.process; +import com.intellij.openapi.util.SystemInfo; import com.intellij.util.Consumer; import com.intellij.util.concurrency.Semaphore; import org.junit.Test; @@ -27,7 +28,7 @@ import static org.junit.Assert.assertTrue; public class ProcessWaitForTest { @Test(timeout = 10000) public void notification() throws IOException, InterruptedException { - File jvm = new File(System.getProperty("java.home"), "bin/java"); + File jvm = new File(System.getProperty("java.home") + (SystemInfo.isWindows ? "\\bin\\java.exe" : "/bin/java")); assertTrue(jvm.canExecute()); final Semaphore semaphore = new Semaphore(); From 85b5e31274a264f5b17a71914628f0f37d29cb35 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 12 Jun 2015 11:06:26 +0200 Subject: [PATCH 20/86] force 'license' dir presence, event if empty --- build/scripts/dist.gant | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 652a97d759bf..510b77437f98 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -144,6 +144,9 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = include(name: "*.*") } } + + ant.mkdir(dir: "license") // in case the license directory is absent, create it + dir("license") { fileset(dir: "${home}/license") } From a632f157f34a691ee6c39694324d9a1306809926 Mon Sep 17 00:00:00 2001 From: Vyacheslav Karpukhin Date: Fri, 12 Jun 2015 11:26:48 +0200 Subject: [PATCH 21/86] Fixed XDebuggerUtilImpl --- .../xdebugger/impl/XDebuggerUtilImpl.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java index cb93462706f6..bc5288599510 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java @@ -33,7 +33,6 @@ 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.openapi.util.AsyncResult; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -130,9 +129,9 @@ public class XDebuggerUtilImpl extends XDebuggerUtil { @NotNull final XSourcePosition position, final boolean temporary, final RelativePoint relativePoint) { - return ApplicationManager.getApplication().runWriteAction(new Computable>() { + return new WriteAction>() { @Override - public AsyncResult compute() { + protected void run(@NotNull Result> result) throws Throwable { final VirtualFile file = position.getFile(); final int line = position.getLine(); final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager(); @@ -173,21 +172,25 @@ public class XDebuggerUtilImpl extends XDebuggerUtil { return FINAL_CHOICE; } }).show(relativePoint); - return res; + result.setResult(res); + return; } else { P properties = (P)variants.get(0).createProperties(); - return AsyncResult.done( - (XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)); + result.setResult(AsyncResult.done( + (XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary))); + return; } } } P properties = type.createBreakpointProperties(file, line); - return AsyncResult.done((XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)); + result.setResult(AsyncResult + .done((XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary))); + return; } - return AsyncResult.rejected(); + result.setResult(AsyncResult.rejected()); } - }); + }.execute().getResultObject(); } @Override From 939f5411d7710f9da86d6df330449f5b241fd8d5 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 12 Jun 2015 11:38:49 +0200 Subject: [PATCH 22/86] force 'license' dir presence, event if empty, attempt 2 --- build/scripts/dist.gant | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 510b77437f98..60495187cc73 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -138,15 +138,14 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = notifyArtifactBuilt(paths.artifacts_jps) } + ant.mkdir(dir: "license") // in case the license directory is absent, create it + layout(paths.distAll) { dir("bin") { fileset(dir: "${home}/bin") { include(name: "*.*") } } - - ant.mkdir(dir: "license") // in case the license directory is absent, create it - dir("license") { fileset(dir: "${home}/license") } From bf5109fa38a4c4505045cfa3ce405e8a7dcf8f6e Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 12 Jun 2015 11:45:05 +0200 Subject: [PATCH 23/86] force 'license' dir presence, event if empty, attempt 2 --- build/scripts/dist.gant | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 60495187cc73..7a7a3ee27b56 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -138,7 +138,7 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = notifyArtifactBuilt(paths.artifacts_jps) } - ant.mkdir(dir: "license") // in case the license directory is absent, create it + ant.mkdir(dir: paths.distAll + "/license") // in case the license directory is absent, create it layout(paths.distAll) { dir("bin") { From c1c90324ecfbaf6f3a794e0e73ece0c7b5e590bd Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 12 Jun 2015 12:12:25 +0200 Subject: [PATCH 24/86] force source 'license' dir presence, event if empty --- build/scripts/dist.gant | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 7a7a3ee27b56..e07bfa65bf18 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -138,7 +138,7 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = notifyArtifactBuilt(paths.artifacts_jps) } - ant.mkdir(dir: paths.distAll + "/license") // in case the license directory is absent, create it +// ant.mkdir(dir: paths.distAll + "/license") // in case the license directory is absent, create it layout(paths.distAll) { dir("bin") { @@ -146,6 +146,9 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = include(name: "*.*") } } + + ant.mkdir(dir: "${home}/license") // in case the source license directory is absent, create it + dir("license") { fileset(dir: "${home}/license") } From e91635109c4972734f40031bd6475826e00efe4c Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 12 Jun 2015 12:12:51 +0200 Subject: [PATCH 25/86] remove comment --- build/scripts/dist.gant | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index e07bfa65bf18..52b48afa2cec 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -138,8 +138,6 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = notifyArtifactBuilt(paths.artifacts_jps) } -// ant.mkdir(dir: paths.distAll + "/license") // in case the license directory is absent, create it - layout(paths.distAll) { dir("bin") { fileset(dir: "${home}/bin") { From f51820a27e13654faf844f78aa84f281ca7f37a1 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 12 Jun 2015 12:45:14 +0200 Subject: [PATCH 26/86] force 'license' dir presence, event if empty in both source and destination locations --- build/scripts/dist.gant | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 52b48afa2cec..3be716082a8c 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -138,6 +138,12 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = notifyArtifactBuilt(paths.artifacts_jps) } + // in case the license directory is absent, create it + mkdir(dir: "${home}/license") + [paths.distWin, paths.distAll, paths.distUnix, paths.distMac].each { + ant.mkdir(dir: it + "/license") + } + layout(paths.distAll) { dir("bin") { fileset(dir: "${home}/bin") { @@ -145,8 +151,6 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = } } - ant.mkdir(dir: "${home}/license") // in case the source license directory is absent, create it - dir("license") { fileset(dir: "${home}/license") } From dca4a75642a00c718f8904316e77c32a5d8bc747 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 12 Jun 2015 15:16:29 +0200 Subject: [PATCH 27/86] restoring 'license' dir for dbide and webstorm --- build/scripts/dist.gant | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 3be716082a8c..607a28263ff1 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -138,12 +138,6 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = notifyArtifactBuilt(paths.artifacts_jps) } - // in case the license directory is absent, create it - mkdir(dir: "${home}/license") - [paths.distWin, paths.distAll, paths.distUnix, paths.distMac].each { - ant.mkdir(dir: it + "/license") - } - layout(paths.distAll) { dir("bin") { fileset(dir: "${home}/bin") { @@ -152,7 +146,9 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = } dir("license") { - fileset(dir: "${home}/license") + fileset(dir: "${home}/license") { + exclude(name: "placeholder.txt") + } } fileset(file: "${home}/LICENSE.txt") fileset(file: "${home}/NOTICE.txt") From 4de06c31fbd8984c6fc0c59c12f95892a8e8802b Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 9 Jun 2015 12:47:55 +0200 Subject: [PATCH 28/86] SSR: keep order of modifiers when replacing annotation --- .../com/intellij/structuralsearch/JavaReplaceHandler.java | 2 +- .../intellij/structuralsearch/StructuralReplaceTest.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaReplaceHandler.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaReplaceHandler.java index b95b01fe08d0..2ae17d8756a9 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaReplaceHandler.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaReplaceHandler.java @@ -269,7 +269,7 @@ public class JavaReplaceHandler extends StructuralReplaceHandler { if (firstChild instanceof PsiModifierList) { final PsiModifierList modifierList = (PsiModifierList)firstChild; for (PsiElement child : modifierList.getChildren()) { - elementParent.add(child); + elementParent.addBefore(child, elementToReplace); } } } diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java index 6c204de6ea05..8086ffc0d86a 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralReplaceTest.java @@ -2259,15 +2259,15 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase { public void testReplaceAnnotation() { String in = "@SuppressWarnings(\"ALL\")\n" + - "class A {}"; + "public class A {}"; String what = "@SuppressWarnings(\"ALL\")"; final String by1 = ""; - assertEquals("class A {}", replacer.testReplace(in, what, by1, options, false)); + assertEquals("public class A {}", replacer.testReplace(in, what, by1, options, false)); final String by2 = "@SuppressWarnings(\"NONE\") @Deprecated"; assertEquals("@SuppressWarnings(\"NONE\") @Deprecated\n" + - "class A {}", replacer.testReplace(in, what, by2, options, false)); + "public class A {}", replacer.testReplace(in, what, by2, options, false)); } public void testReplacePolyadicExpression() { From daad338196544c0e603edbb4e5ef270e882e8927 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 12 Jun 2015 17:34:58 +0200 Subject: [PATCH 29/86] EA-69413 (AIOOBE: AbstractMethodOverridesAbstractMethodInspection$AbstractMethodOverridesAbstractMethodVisitor.methodsHaveSameAnnotations) --- .../AbstractMethodOverridesAbstractMethodInspection.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/AbstractMethodOverridesAbstractMethodInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/AbstractMethodOverridesAbstractMethodInspection.java index 137374f12006..aeb7fc2e69b5 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/AbstractMethodOverridesAbstractMethodInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/AbstractMethodOverridesAbstractMethodInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2015 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -148,6 +148,9 @@ public class AbstractMethodOverridesAbstractMethodInspection extends BaseInspect final PsiParameter[] superParameters = superParameterList.getParameters(); final PsiParameterList parameterList = method.getParameterList(); final PsiParameter[] parameters = parameterList.getParameters(); + if (parameters.length != superParameters.length) { + return false; + } for (int i = 0, length = superParameters.length; i < length; i++) { final PsiParameter superParameter = superParameters[i]; final PsiParameter parameter = parameters[i]; @@ -171,7 +174,7 @@ public class AbstractMethodOverridesAbstractMethodInspection extends BaseInspect final Set annotationsSet = new HashSet(Arrays.asList(superAnnotations)); for (PsiAnnotation annotation : annotations) { final String qualifiedName = annotation.getQualifiedName(); - if ("java.lang.Override".equals(qualifiedName)) { + if (CommonClassNames.JAVA_LANG_OVERRIDE.equals(qualifiedName)) { continue; } if (!annotationsSet.contains(annotation)) { From d8078802d3d2cbc393049cf51a6f7f38c4f32fbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Fri, 12 Jun 2015 17:39:22 +0200 Subject: [PATCH 30/86] JavaParametersUtil.getClasspathType: add @MagicConstant to return value --- .../impl/src/com/intellij/execution/util/JavaParametersUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java b/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java index eede2edda506..0fe20076493b 100644 --- a/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java +++ b/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java @@ -68,6 +68,7 @@ public class JavaParametersUtil { parameters.getVMParametersList().addParametersString(vmParameters); } + @MagicConstant(valuesFromClass = JavaParameters.class) public static int getClasspathType(final RunConfigurationModule configurationModule, final String mainClassName, final boolean classMustHaveSource) throws CantRunException { final Module module = configurationModule.getModule(); From fab15d134c11d5d279ca382b56a1223f6a347a86 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 12 Jun 2015 18:52:31 +0300 Subject: [PATCH 31/86] methods to prevent App Nap when needed --- .../util/resources/misc/registry.properties | 3 +++ .../intellij/ui/mac/foundation/MacUtil.java | 26 +++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 9f8ea66e2b7b..941f2f758cc6 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -74,6 +74,9 @@ idea.fix.mac.env=true idea.fix.mac.env.restartRequired=true idea.fix.mac.env.description=On Mac, use shell environment for external processes. +idea.mac.prevent.app.nap=false +idea.mac.prevent.app.nap.description=Prevent app nap during indexing and inspection + ide.x11.override.wm=true ide.appIcon.progress=true diff --git a/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java b/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java index 8ee9ee9206fb..58b6cdd53591 100644 --- a/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java +++ b/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java @@ -33,8 +33,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.concurrent.atomic.AtomicBoolean; -import static com.intellij.ui.mac.foundation.Foundation.invoke; -import static com.intellij.ui.mac.foundation.Foundation.toStringViaUTF8; +import static com.intellij.ui.mac.foundation.Foundation.*; /** * @author pegov @@ -192,4 +191,27 @@ public class MacUtil { } return windowTitle; } + + public static Object wakeUpNeo(String reason) { + // http://lists.apple.com/archives/java-dev/2014/Feb/msg00053.html + // https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSProcessInfo_Class/index.html#//apple_ref/c/tdef/NSActivityOptions + if (SystemInfo.isMacOSMavericks && Registry.is("idea.mac.prevent.app.nap")) { + ID processInfo = invoke("NSProcessInfo", "processInfo"); + ID activity = invoke(processInfo, "beginActivityWithOptions:reason:", + (0x00FFFFFFL & ~(1L << 20)) /* NSActivityUserInitiatedAllowingIdleSystemSleep */ | + 0xFF00000000L /* NSActivityLatencyCritical */, + nsString(reason)); + cfRetain(activity); + return activity; + } + return null; + } + + public static void matrixHasYou(Object activity) { + if (activity != null) { + ID processInfo = invoke("NSProcessInfo", "processInfo"); + invoke(processInfo, "endActivity:", activity); + cfRelease((ID)activity); + } + } } From 2123f478a4c002f3a3da50fc669c4be9143bc4f3 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 12 Jun 2015 20:27:06 +0300 Subject: [PATCH 32/86] prevent App Nap during progress indicators --- .../openapi/progress/util/AbstractProgressIndicatorBase.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java b/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java index af8546cb6147..2cf43d397fd4 100644 --- a/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java +++ b/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java @@ -23,6 +23,7 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.UserDataHolderBase; +import com.intellij.ui.mac.foundation.MacUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.DoubleArrayList; import com.intellij.util.containers.Stack; @@ -43,6 +44,7 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements private volatile boolean myFinished; private volatile boolean myIndeterminate; + private volatile Object myMacActivity; private Stack myTextStack; private DoubleArrayList myFractionStack; @@ -68,6 +70,7 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements myText = ""; myFraction = 0; myText2 = ""; + myMacActivity = MacUtil.wakeUpNeo(toString()); myRunning = true; } @@ -82,6 +85,8 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements LOG.assertTrue(myRunning, "stop() should be called only if start() called before"); myRunning = false; myFinished = true; + MacUtil.matrixHasYou(myMacActivity); + myMacActivity = null; } @Override From f97b4434e7f43828bdb64748221fae530f3def2e Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sat, 13 Jun 2015 21:51:23 +0200 Subject: [PATCH 33/86] semi-transparent focus border looks bad (artifacts at the bottom) with editor rectangle --- .../intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java index ea36ede553c8..1d129e4beb0c 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaComboBoxUI.java @@ -342,6 +342,9 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border { g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); final int R = JBUI.scale(5); + if (hasFocus) { + g.setClip(2, 2, comboBox.getWidth()- 4, comboBox.getHeight() - 4); //todo[kb] check HiDPI + } if (editor != null && comboBox.isEditable()) { ((JComponent)editor).setBorder(null); g.setColor(editor.getBackground()); @@ -351,11 +354,11 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border { g.setColor(editor.getBackground()); g.fillRect(xxx, y + 1, 5, H); } else { - g.setColor(comboBox.getBackground()); + g.setColor(UIUtil.getPanelBackground()); g.fillRoundRect(x + 1, y + 1, W, H, R, R); g.setColor(getArrowButtonFillColor(arrowButton.getBackground())); g.fillRoundRect(xxx, y + 1, width - xxx, H, R, R); - g.setColor(comboBox.getBackground()); + g.setColor(UIUtil.getPanelBackground()); g.fillRect(xxx, y + 1, 5, H); } final Color borderColor = getBorderColor();//ColorUtil.shift(UIUtil.getBorderColor(), 4); @@ -368,6 +371,7 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border { paintCurrentValue(g, r, false); if (hasFocus) { + g.setClip(0, 0, comboBox.getWidth(), comboBox.getHeight()); DarculaUIUtil.paintFocusRing(g, JBUI.scale(2), JBUI.scale(2), width - JBUI.scale(4), height - JBUI.scale(4)); } else { From e1075a48ab007755ef270908450fedb448d8f2ce Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sat, 13 Jun 2015 22:15:52 +0200 Subject: [PATCH 34/86] fix artifacts with painting when combobox height is more than arrow button height --- .../ide/ui/laf/intellij/MacIntelliJComboBoxUI.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java index 4a48ffdcfe82..b0c4cc52b53c 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java @@ -189,6 +189,7 @@ public class MacIntelliJComboBoxUI extends BasicComboBoxUI implements Border, UI @Override protected Rectangle rectangleForCurrentValue() { Rectangle rect = super.rectangleForCurrentValue(); + rect.height=Math.min(rect.height, COMBOBOX.getIconHeight()); rect.y+=2; rect.x+=5; rect.height-=4; @@ -262,12 +263,13 @@ public class MacIntelliJComboBoxUI extends BasicComboBoxUI implements Border, UI public void paint(Graphics g, JComponent c) { super.paint(g, c); - int stop = arrowButton.getBounds().x; + Rectangle r = arrowButton.getBounds(); + int stop = r.x; g.setClip(0,0, stop, COMBOBOX.getIconHeight()); - COMBOBOX_LEFT.paintIcon(c,g,0,0); + COMBOBOX_LEFT.paintIcon(c,g,0,r.y); int x = COMBOBOX_LEFT.getIconWidth(); while (x < stop) { - COMBOBOX_TOP_BOTTOM.paintIcon(c, g, x, 0); + COMBOBOX_TOP_BOTTOM.paintIcon(c, g, x, r.y); x+=COMBOBOX_TOP_BOTTOM.getIconWidth(); } ((Graphics2D)g).scale(0.5d, 0.5d); From a0815608f9dff966f6d10bfcd58eb9ce9b681636 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Sat, 13 Jun 2015 15:56:05 +0300 Subject: [PATCH 35/86] soft wrap model change validation --- .../LineOrientedDocumentChangeAdapter.java | 83 ------------------- .../mapping/CachingSoftWrapDataMapper.java | 23 ++--- 2 files changed, 12 insertions(+), 94 deletions(-) delete mode 100644 platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/LineOrientedDocumentChangeAdapter.java diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/LineOrientedDocumentChangeAdapter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/LineOrientedDocumentChangeAdapter.java deleted file mode 100644 index 3a715233d044..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/LineOrientedDocumentChangeAdapter.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.editor.impl.softwrap; - -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.event.DocumentListener; -import com.intellij.openapi.editor.ex.PrioritizedDocumentListener; - -/** - * Adapter class for {@link DocumentListener} interface that allows to represent document change events - * in terms of logical lines affected by it. - * - * @author Denis Zhdanov - * @since Jul 7, 2010 4:24:52 PM - */ -public abstract class LineOrientedDocumentChangeAdapter implements PrioritizedDocumentListener { - - @Override - public void beforeDocumentChange(DocumentEvent event) { - Document document = event.getDocument(); - int startLine = document.getLineNumber(normalize(event.getDocument(), event.getOffset())); - int endLine = document.getLineNumber(normalize(event.getDocument(), event.getOffset() + event.getOldLength())); - int symbolsDifference = event.getNewLength() - event.getOldLength(); - beforeDocumentChange(startLine, endLine, symbolsDifference); - } - - @Override - public void documentChanged(DocumentEvent event) { - Document document = event.getDocument(); - int startLine = document.getLineNumber(normalize(event.getDocument(), event.getOffset())); - int endLine = document.getLineNumber(normalize(event.getDocument(), event.getOffset() + event.getNewLength())); - int symbolsDifference = event.getNewLength() - event.getOldLength(); - afterDocumentChange(startLine, endLine, symbolsDifference); - } - - @Override - public int getPriority() { - return Integer.MAX_VALUE; - } - - /** - * Callback adapter method for {@link DocumentListener#beforeDocumentChange(DocumentEvent)} event. - * - * @param startLine first logical document line affected by the target event (inclusive) - * @param endLine old last logical document line affected by the target event (inclusive) - * @param symbolsDifference difference in number in symbols applied to the target document - */ - public abstract void beforeDocumentChange(int startLine, int endLine, int symbolsDifference); - - /** - * Callback adapter method for {@link DocumentListener#documentChanged(DocumentEvent)} event. - * - * @param startLine first logical document line affected by the target event (inclusive) - * @param endLine new last logical document line affected by the target event (inclusive) - * @param symbolsDifference difference in number in symbols applied to the target document - */ - public abstract void afterDocumentChange(int startLine, int endLine, int symbolsDifference); - - private static int normalize(Document document, int offset) { - if (offset < 0) { - return 0; - } - - if (offset >= document.getTextLength()) { - return Math.max(document.getTextLength() - 1, 0); - } - return offset; - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CachingSoftWrapDataMapper.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CachingSoftWrapDataMapper.java index 67923b0e49a0..a2cda73530a4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CachingSoftWrapDataMapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/CachingSoftWrapDataMapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -566,7 +566,8 @@ public class CachingSoftWrapDataMapper implements SoftWrapAwareDocumentParsingLi int borderSoftWrapColumnDiff = 0; int borderSoftWrapLinesBeforeDiff = 0; int borderSoftWrapLinesCurrentDiff = 0; - for (int i = 0; i < myAffectedByUpdateCacheEntries.size(); i++) { + int affectedEntriesCount = myAffectedByUpdateCacheEntries.size(); + for (int i = 0; i < affectedEntriesCount; i++) { CacheEntry entry = myAffectedByUpdateCacheEntries.get(i); if (firstIndex < 0) { if (entry.startOffset < recalcEndOffsetTranslated) { @@ -574,15 +575,12 @@ public class CachingSoftWrapDataMapper implements SoftWrapAwareDocumentParsingLi continue; } firstIndex = i; - if (lastEntry != null) { - borderLogicalLine = lastEntry.endLogicalLine; - if (entry.startLogicalLine + logicalLinesDiff == borderLogicalLine) { - borderColumnDiff = lastEntry.endLogicalColumn - entry.startLogicalColumn; - borderSoftWrapLinesBeforeDiff = lastEntry.endSoftWrapLinesBefore - entry.startSoftWrapLinesBefore; - borderSoftWrapLinesCurrentDiff = lastEntry.endSoftWrapLinesCurrent - entry.startSoftWrapLinesCurrent + 1; - borderFoldedColumnDiff = lastEntry.endFoldingColumnDiff - entry.startFoldingColumnDiff; - borderSoftWrapColumnDiff = - borderColumnDiff - borderFoldedColumnDiff; - } + if (lastEntry != null && entry.startLogicalLine + logicalLinesDiff == borderLogicalLine) { + borderColumnDiff = lastEntry.endLogicalColumn - entry.startLogicalColumn; + borderSoftWrapLinesBeforeDiff = lastEntry.endSoftWrapLinesBefore - entry.startSoftWrapLinesBefore; + borderSoftWrapLinesCurrentDiff = lastEntry.endSoftWrapLinesCurrent - entry.startSoftWrapLinesCurrent + 1; + borderFoldedColumnDiff = lastEntry.endFoldingColumnDiff - entry.startFoldingColumnDiff; + borderSoftWrapColumnDiff = -borderColumnDiff - borderFoldedColumnDiff; } if (lengthDiff == 0 && logicalLinesDiff == 0 && foldedLinesDiff == 0 && softWrappedLinesDiff == 0 && borderColumnDiff == 0 && borderSoftWrapColumnDiff == 0 && borderFoldedColumnDiff == 0 @@ -626,6 +624,9 @@ public class CachingSoftWrapDataMapper implements SoftWrapAwareDocumentParsingLi LOG.error("Invalid soft wrap cache update", new Attachment("state.txt", myEditor.getSoftWrapModel().toString())); } } + if (myAffectedByUpdateCacheEntries.get(affectedEntriesCount - 1).endOffset > myEditor.getDocument().getTextLength()) { + LOG.error("Invalid soft wrap cache entries emerged", new Attachment("state.txt", myEditor.getSoftWrapModel().toString())); + } myCache.addAll(myAffectedByUpdateCacheEntries.subList(firstIndex, myAffectedByUpdateCacheEntries.size())); } myAffectedByUpdateCacheEntries.clear(); From 94841d36b4b05c70e9874003ee0bd3d969550c30 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Sat, 13 Jun 2015 21:59:52 +0300 Subject: [PATCH 36/86] fix mess in editor after reformat when soft wraps are enabled (make sure bulk mode start/finish events always come in proper order) --- .../openapi/editor/impl/DocumentImpl.java | 22 ++++++++++++----- .../ex/util/LexerEditorHighlighter.java | 24 ++++++++++--------- .../openapi/editor/impl/EditorImplTest.java | 12 +++++++++- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java index 74354e30a14a..ea6834e5695e 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/DocumentImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,6 +82,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { private boolean myEventsHandling = false; private final boolean myAssertThreading; private volatile boolean myDoingBulkUpdate = false; + private boolean myUpdatingBulkModeStatus; private volatile boolean myAcceptSlashR = false; private boolean myChangeInProgress; private volatile int myBufferSize; @@ -971,12 +972,21 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx { // do not fire listeners or otherwise updateStarted() will be called more times than updateFinished() return; } - myDoingBulkUpdate = value; - if (value) { - getPublisher().updateStarted(this); + if (myUpdatingBulkModeStatus) { + throw new IllegalStateException("Detected bulk mode status update from DocumentBulkUpdateListener"); } - else { - getPublisher().updateFinished(this); + myUpdatingBulkModeStatus = true; + try { + myDoingBulkUpdate = value; + if (value) { + getPublisher().updateStarted(this); + } + else { + getPublisher().updateFinished(this); + } + } + finally { + myUpdatingBulkModeStatus = false; } } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java index e51f2f81c7ea..84119ad2f0ec 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -78,9 +78,7 @@ public class LexerEditorHighlighter implements EditorHighlighter, PrioritizedDoc public final synchronized boolean checkContentIsEqualTo(CharSequence sequence) { final Document document = getDocument(); - return document instanceof DocumentEx && - Comparing.equal(document.getImmutableCharSequence(), sequence) && - !((DocumentEx)document).isInBulkUpdate(); + return document != null && isInSyncWithDocument() && Comparing.equal(document.getImmutableCharSequence(), sequence); } public EditorColorsScheme getScheme() { @@ -107,13 +105,12 @@ public class LexerEditorHighlighter implements EditorHighlighter, PrioritizedDoc @Override public HighlighterIterator createIterator(int startOffset) { synchronized (this) { - final Document document = getDocument(); - if(document instanceof DocumentEx && ((DocumentEx)document).isInBulkUpdate()) { - ((DocumentEx)document).setInBulkUpdate(false); // bulk mode failed - } - - if (mySegments.getSegmentCount() == 0 && document != null && document.getTextLength() > 0) { - // bulk mode was reset + if (!isInSyncWithDocument()) { + final Document document = getDocument(); + assert document != null; + if(document instanceof DocumentEx && ((DocumentEx)document).isInBulkUpdate()) { + ((DocumentEx)document).setInBulkUpdate(false); // bulk mode failed + } doSetText(document.getCharsSequence()); } @@ -131,6 +128,11 @@ public class LexerEditorHighlighter implements EditorHighlighter, PrioritizedDoc Project project = myEditor.getProject(); return project != null && !project.isDisposed(); } + + private boolean isInSyncWithDocument() { + Document document = getDocument(); + return document == null || document.getTextLength() == 0 || mySegments.getSegmentCount() > 0; + } private static boolean isInitialState(int data) { return data >= 0; diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java index 388b349b30a7..f97ea942da7f 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -141,4 +141,14 @@ public class EditorImplTest extends AbstractEditorTest { assertEquals(new LogicalPosition(0, 3), myEditor.getCaretModel().getLogicalPosition()); assertEquals(new VisualPosition(0, 3), myEditor.getCaretModel().getVisualPosition()); } + + public void testSoftWrapModeUpdateDuringBulkModeChange() throws Exception { + initText("long long line"); + configureSoftWraps(12); + DocumentEx document = (DocumentEx)myEditor.getDocument(); + document.setInBulkUpdate(true); + document.replaceString(4, 5, "-"); + document.setInBulkUpdate(false); + assertEquals(new VisualPosition(1, 5), myEditor.getCaretModel().getVisualPosition()); + } } From 775701c687655e3b87faddbf32b81bc66b2e8b88 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sat, 13 Jun 2015 23:35:38 +0200 Subject: [PATCH 37/86] can't read value of focused combobox --- .../intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java index b0c4cc52b53c..975fdf129803 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/MacIntelliJComboBoxUI.java @@ -258,6 +258,9 @@ public class MacIntelliJComboBoxUI extends BasicComboBoxUI implements Border, UI g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); } + public void paintCurrentValue(Graphics g,Rectangle bounds,boolean hasFocus) { + super.paintCurrentValue(g, bounds, comboBox.isPopupVisible()); + } @Override public void paint(Graphics g, JComponent c) { From 49ec73af7f34c03eb03a9964628bebc5c8af4f24 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 12 Jun 2015 16:26:10 +0300 Subject: [PATCH 38/86] util: optimal string alignment calculation --- .../util/text/LevenshteinDistance.java | 29 ++------ .../com/intellij/util/text/EditDistance.java | 67 +++++++++++++++++++ .../intellij/util/text/EditDistanceTest.java | 56 ++++++++++++++++ .../spellchecker/engine/BaseSpellChecker.java | 7 +- 4 files changed, 132 insertions(+), 27 deletions(-) create mode 100644 platform/util/src/com/intellij/util/text/EditDistance.java create mode 100644 platform/util/testSrc/com/intellij/util/text/EditDistanceTest.java diff --git a/platform/util/src/com/intellij/openapi/util/text/LevenshteinDistance.java b/platform/util/src/com/intellij/openapi/util/text/LevenshteinDistance.java index 0f4e042048cd..b66d61ad0568 100644 --- a/platform/util/src/com/intellij/openapi/util/text/LevenshteinDistance.java +++ b/platform/util/src/com/intellij/openapi/util/text/LevenshteinDistance.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,29 +15,12 @@ */ package com.intellij.openapi.util.text; +import com.intellij.util.text.EditDistance; + +/** @deprecated use {@link EditDistance} (to be removed in IDEA 17) */ +@SuppressWarnings("unused") public class LevenshteinDistance { - - private static int minimum(int a, int b, int c) { - return Math.min(Math.min(a, b), c); - } - public int calculateMetrics(CharSequence str1, CharSequence str2) { - int[][] distance = new int[str1.length() + 1][str2.length() + 1]; - - for (int i = 0; i <= str1.length(); i++) { - distance[i][0] = i; - } - for (int j = 0; j <= str2.length(); j++) { - distance[0][j] = j; - } - - for (int i = 1; i <= str1.length(); i++) { - for (int j = 1; j <= str2.length(); j++) { - distance[i][j] = minimum(distance[i - 1][j] + 1, distance[i][j - 1] + 1, - distance[i - 1][j - 1] + ((str1.charAt(i - 1) == str2.charAt(j - 1)) ? 0 : 1)); - } - } - - return distance[str1.length()][str2.length()]; + return EditDistance.levenshtein(str1, str2, true); } } diff --git a/platform/util/src/com/intellij/util/text/EditDistance.java b/platform/util/src/com/intellij/util/text/EditDistance.java new file mode 100644 index 000000000000..e97da22aa108 --- /dev/null +++ b/platform/util/src/com/intellij/util/text/EditDistance.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.text; + +import org.jetbrains.annotations.NotNull; + +public class EditDistance { + private EditDistance() { } + + public static int levenshtein(@NotNull CharSequence str1, @NotNull CharSequence str2, boolean caseSensitive) { + // Wagner-Fischer implementation of Levenshtein distance + // (http://en.wikipedia.org/wiki/Wagner-Fischer_algorithm) + int[][] d = prepare(str1.length(), str2.length()); + for (int i = 1; i <= str1.length(); i++) { + for (int j = 1; j <= str2.length(); j++) { + int cost = equal(str1.charAt(i - 1), str2.charAt(j - 1), caseSensitive) ? 0 : 1; + d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost); + } + } + return d[str1.length()][str2.length()]; + } + + public static int optimalAlignment(@NotNull CharSequence str1, @NotNull CharSequence str2, boolean caseSensitive) { + // extension of the above with additional case of adjacent transpositions + // (http://en.wikipedia.org/wiki/Damerau-Levenshtein_distance#Optimal_string_alignment_distance) + int[][] d = prepare(str1.length(), str2.length()); + for (int i = 1; i <= str1.length(); i++) { + for (int j = 1; j <= str2.length(); j++) { + int cost = equal(str1.charAt(i - 1), str2.charAt(j - 1), caseSensitive) ? 0 : 1; + d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost); + if (i > 1 && j > 1 && + equal(str1.charAt(i - 1), str2.charAt(j - 2), caseSensitive) && equal(str1.charAt(i - 2), str2.charAt(j - 1), caseSensitive)) { + d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost); + } + } + } + return d[str1.length()][str2.length()]; + } + + private static int[][] prepare(int length1, int length2) { + int[][] d = new int[length1 + 1][length2 + 1]; + for (int i = 0; i <= length1; i++) d[i][0] = i; + for (int j = 0; j <= length2; j++) d[0][j] = j; + return d; + } + + private static boolean equal(char c1, char c2, boolean caseSensitive) { + return caseSensitive ? c1 == c2 : Character.toLowerCase(c1) == Character.toLowerCase(c2); + } + + private static int min(int a, int b, int c) { + return Math.min(Math.min(a, b), c); + } +} diff --git a/platform/util/testSrc/com/intellij/util/text/EditDistanceTest.java b/platform/util/testSrc/com/intellij/util/text/EditDistanceTest.java new file mode 100644 index 000000000000..084d1791b007 --- /dev/null +++ b/platform/util/testSrc/com/intellij/util/text/EditDistanceTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.text; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class EditDistanceTest { + @Test + public void levenshtein() { + assertEquals(0, EditDistance.levenshtein("", "", true)); + assertEquals(0, EditDistance.levenshtein("AA", "AA", true)); + assertEquals(1, EditDistance.levenshtein("AA", "Aa", true)); + assertEquals(2, EditDistance.levenshtein("AA", "aa", true)); + assertEquals(2, EditDistance.levenshtein("ab", "ba", true)); + } + + @Test + public void levenshteinCaseInsensitive() { + assertEquals(0, EditDistance.levenshtein("", "", false)); + assertEquals(0, EditDistance.levenshtein("AA", "AA", false)); + assertEquals(0, EditDistance.levenshtein("AA", "Aa", false)); + assertEquals(0, EditDistance.levenshtein("AA", "aa", false)); + assertEquals(2, EditDistance.levenshtein("ab", "ba", false)); + } + + @Test + public void optimalAlignment() { + assertEquals(1, EditDistance.optimalAlignment("ab", "ba", true)); + assertEquals(2, EditDistance.optimalAlignment("AB", "ba", true)); + assertEquals(3, EditDistance.optimalAlignment("ca", "abc", true)); + assertEquals(3, EditDistance.optimalAlignment("Ca", "abc", true)); + } + + @Test + public void optimalAlignmentCaseInsensitive() { + assertEquals(1, EditDistance.optimalAlignment("ab", "ba", false)); + assertEquals(1, EditDistance.optimalAlignment("AB", "ba", false)); + assertEquals(3, EditDistance.optimalAlignment("ca", "abc", false)); + assertEquals(3, EditDistance.optimalAlignment("Ca", "abc", false)); + } +} \ No newline at end of file diff --git a/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java b/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java index d5a0674f8e4c..c4ce805d014b 100644 --- a/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java +++ b/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.text.LevenshteinDistance; +import com.intellij.util.text.EditDistance; import com.intellij.openapi.util.text.StringUtil; import com.intellij.spellchecker.compress.CompressedDictionary; import com.intellij.spellchecker.dictionary.Dictionary; @@ -46,7 +46,6 @@ public class BaseSpellChecker implements SpellCheckerEngine { private final Set dictionaries = new HashSet(); private final List bundledDictionaries = ContainerUtil.createLockFreeCopyOnWriteList(); - private final LevenshteinDistance metrics = new LevenshteinDistance(); private final AtomicBoolean myLoadingDictionaries = new AtomicBoolean(false); private final List>> myDictionariesToLoad = ContainerUtil.createLockFreeCopyOnWriteList(); @@ -244,7 +243,7 @@ public class BaseSpellChecker implements SpellCheckerEngine { List rawSuggestions = restore(transformed.charAt(0), 0, Integer.MAX_VALUE, bundledDictionaries); rawSuggestions.addAll(restore(word.charAt(0), 0, Integer.MAX_VALUE, dictionaries)); for (String rawSuggestion : rawSuggestions) { - final int distance = metrics.calculateMetrics(transformed, rawSuggestion); + int distance = EditDistance.levenshtein(transformed, rawSuggestion, true); suggestions.add(new Suggestion(rawSuggestion, distance)); } List result = new ArrayList(); From 9486d4ef3e28692bd07df62f3cd52cf5915dee46 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 12 Jun 2015 23:17:22 +0300 Subject: [PATCH 39/86] Cleanup (typo) --- .../com/intellij/util/xmlb/PropertyAccessor.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java b/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java index 0bc808405bc9..60a7152a01ff 100644 --- a/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java +++ b/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java @@ -29,7 +29,7 @@ class PropertyAccessor implements MutableAccessor { private final String myName; private final Class myType; private final Method myReadMethod; - private final Method setter; + private final Method myWriteMethod; private final Type myGenericType; public PropertyAccessor(PropertyDescriptor descriptor) { @@ -40,15 +40,14 @@ class PropertyAccessor implements MutableAccessor { myName = name; myType = type; myReadMethod = readMethod; - setter = writeMethod; + myWriteMethod = writeMethod; myGenericType = myReadMethod.getGenericReturnType(); try { myReadMethod.setAccessible(true); - setter.setAccessible(true); - } - catch (SecurityException ignored) { + myWriteMethod.setAccessible(true); } + catch (SecurityException ignored) { } } @Override @@ -67,7 +66,7 @@ class PropertyAccessor implements MutableAccessor { @Override public void set(@NotNull Object host, @Nullable Object value) { try { - setter.invoke(host, value); + myWriteMethod.invoke(host, value); } catch (IllegalAccessException e) { throw new XmlSerializationException(e); @@ -110,7 +109,8 @@ class PropertyAccessor implements MutableAccessor { @Override public T getAnnotation(@NotNull Class annotationClass) { T annotation = myReadMethod.getAnnotation(annotationClass); - return annotation == null ? setter.getAnnotation(annotationClass) : annotation; + if (annotation == null) annotation = myWriteMethod.getAnnotation(annotationClass); + return annotation; } @Override From b0c4eca67ba6b7537f4b1494db5fa99307f8eeb2 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Sat, 13 Jun 2015 14:31:06 +0300 Subject: [PATCH 40/86] Cleanup (less collection allocations) --- .../spellchecker/SpellCheckerManager.java | 27 ++----- .../compress/CompressedDictionary.java | 35 +++++---- .../spellchecker/engine/BaseSpellChecker.java | 71 ++++++------------- 3 files changed, 49 insertions(+), 84 deletions(-) diff --git a/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java b/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java index 660990d53368..57106fecbdac 100644 --- a/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java +++ b/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,22 +43,15 @@ import java.io.InputStream; import java.util.*; public class SpellCheckerManager { - private static final Logger LOG = Logger.getInstance("#com.intellij.spellchecker.SpellCheckerManager"); private static final int MAX_SUGGESTIONS_THRESHOLD = 5; private static final int MAX_METRICS = 1; private final Project project; - private SpellCheckerEngine spellChecker; - private EditableDictionary userDictionary; - - - @NotNull private final SuggestionProvider suggestionProvider = new BaseSuggestionProvider(this); - private final SpellCheckerSettings settings; public static SpellCheckerManager getInstance(Project project) { @@ -76,7 +69,6 @@ public class SpellCheckerManager { fillEngineDictionary(); } - public void updateBundledDictionaries(final List removedDictionaries) { for (BundledDictionaryProvider provider : Extensions.getExtensions(BundledDictionaryProvider.EP_NAME)) { for (String dictionary : provider.getBundledDictionaries()) { @@ -179,10 +171,8 @@ public class SpellCheckerManager { spellChecker.loadDictionary(loader); } userDictionary = stateLoader.getDictionary(); - } - public boolean hasProblem(@NotNull String word) { return !spellChecker.isCorrect(word); } @@ -202,8 +192,6 @@ public class SpellCheckerManager { restartInspections(); } - - @NotNull public static List getBundledDictionaries() { final ArrayList dictionaries = new ArrayList(); @@ -223,27 +211,24 @@ public class SpellCheckerManager { return suggestionProvider.getSuggestions(text); } - @NotNull protected List getRawSuggestions(@NotNull String word) { if (!spellChecker.isCorrect(word)) { List suggestions = spellChecker.getSuggestions(word, MAX_SUGGESTIONS_THRESHOLD, MAX_METRICS); if (!suggestions.isEmpty()) { - boolean capitalized = Strings.isCapitalized(word); - boolean upperCases = Strings.isUpperCase(word); - if (capitalized) { + if (Strings.isCapitalized(word)) { Strings.capitalize(suggestions); } - else if (upperCases) { + else if (Strings.isUpperCase(word)) { Strings.upperCase(suggestions); } + Set unique = new LinkedHashSet(suggestions); + return unique.size() < suggestions.size() ? new ArrayList(unique) : suggestions; } - return new ArrayList(new LinkedHashSet(suggestions)); } return Collections.emptyList(); } - public static void restartInspections() { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override @@ -257,6 +242,4 @@ public class SpellCheckerManager { } }); } - - } diff --git a/spellchecker/src/com/intellij/spellchecker/compress/CompressedDictionary.java b/spellchecker/src/com/intellij/spellchecker/compress/CompressedDictionary.java index 16ca7ca8b92a..7914aded01a8 100644 --- a/spellchecker/src/com/intellij/spellchecker/compress/CompressedDictionary.java +++ b/spellchecker/src/com/intellij/spellchecker/compress/CompressedDictionary.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -89,13 +89,26 @@ public final class CompressedDictionary implements Dictionary { return new TreeSet(COMPARATOR); } - @NotNull + /** @deprecated use {@link #getWords(char, int, int, Collection)} (to be removed in IDEA 17) */ + @SuppressWarnings("unused") public List getWords(char first, int minLength, int maxLength) { - int index = alphabet.getIndex(first, false); List result = new ArrayList(); - if (index == -1) { - return result; - } + getWords(first, minLength, maxLength, result); + return result; + } + + /** @deprecated use {@link #getWords(char, int, int, Collection)} (to be removed in IDEA 17) */ + @SuppressWarnings("unused") + public List getWords(char first) { + List result = new ArrayList(); + getWords(first, 0, Integer.MAX_VALUE, result); + return result; + } + + public void getWords(char first, int minLength, int maxLength, @NotNull Collection result) { + int index = alphabet.getIndex(first, false); + if (index == -1) return; + int i = 0; for (byte[] data : words) { int length = lengths[i]; @@ -110,12 +123,6 @@ public final class CompressedDictionary implements Dictionary { } i++; } - return result; - } - - @NotNull - public List getWords(char first) { - return getWords(first, 0, Integer.MAX_VALUE); } @NotNull @@ -149,9 +156,9 @@ public final class CompressedDictionary implements Dictionary { @Override public Set getWords() { Set words = new THashSet(); - for (int i=0; i<=alphabet.getLastIndexUsed();i++) { + for (int i = 0; i <= alphabet.getLastIndexUsed(); i++) { char letter = alphabet.getLetter(i); - words.addAll(getWords(letter)); + getWords(letter, 0, Integer.MAX_VALUE, words); } return words; } diff --git a/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java b/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java index c4ce805d014b..a62777dc4070 100644 --- a/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java +++ b/spellchecker/src/com/intellij/spellchecker/engine/BaseSpellChecker.java @@ -38,12 +38,10 @@ import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; - public class BaseSpellChecker implements SpellCheckerEngine { static final Logger LOG = Logger.getInstance("#com.intellij.spellchecker.engine.BaseSpellChecker"); private final Transformation transform = new Transformation(); - private final Set dictionaries = new HashSet(); private final List bundledDictionaries = ContainerUtil.createLockFreeCopyOnWriteList(); @@ -55,7 +53,6 @@ public class BaseSpellChecker implements SpellCheckerEngine { myProject = project; } - @Override public void loadDictionary(@NotNull Loader loader) { if (loader instanceof EditableDictionaryLoader) { @@ -138,7 +135,6 @@ public class BaseSpellChecker implements SpellCheckerEngine { } }; - StartupManager.getInstance(myProject).runWhenProjectIsInitialized(runnable); } @@ -160,37 +156,26 @@ public class BaseSpellChecker implements SpellCheckerEngine { return transform; } - @NotNull - private static List restore(char startFrom, int i, int j, @NotNull Collection dictionaries) { - List results = new ArrayList(); - + private static void restore(char startFrom, int i, int j, Collection dictionaries, Collection result) { for (Dictionary o : dictionaries) { - results.addAll(restore(startFrom, i, j, o)); + restore(startFrom, i, j, o, result); } - return results; } - @NotNull - private static List restore(final char first, final int i, final int j, @NotNull Dictionary dictionary) { - final List result = new ArrayList(); + private static void restore(final char first, final int i, final int j, Dictionary dictionary, final Collection result) { if (dictionary instanceof CompressedDictionary) { - result.addAll(((CompressedDictionary)dictionary).getWords(first, i, j)); + ((CompressedDictionary)dictionary).getWords(first, i, j, result); } else { dictionary.traverse(new Consumer() { @Override public void consume(String s) { - if (StringUtil.isEmpty(s)) { - return; - } - if (s.charAt(0) == first && s.length() >= i && s.length() <= j) { + if (!StringUtil.isEmpty(s) && s.charAt(0) == first && s.length() >= i && s.length() <= j) { result.add(s); } } }); } - - return result; } /** @@ -203,13 +188,10 @@ public class BaseSpellChecker implements SpellCheckerEngine { return -1; } - //System.out.println("dictionaries = " + dictionaries); int errors = 0; for (Dictionary dictionary : dictionaries) { if (dictionary == null) continue; - //System.out.print("\tBSC.isCorrect " + transformed + " " + dictionary); Boolean contains = dictionary.contains(transformed); - //System.out.println("\tcontains = " + contains); if (contains==null) ++errors; else if (contains) return 0; } @@ -219,57 +201,50 @@ public class BaseSpellChecker implements SpellCheckerEngine { @Override public boolean isCorrect(@NotNull String word) { - //System.out.println("---\n"+word); final String transformed = transform.transform(word); if (myLoadingDictionaries.get() || transformed == null) { return true; } int bundled = isCorrect(transformed, bundledDictionaries); int user = isCorrect(transformed, dictionaries); - //System.out.println("bundled = " + bundled); - //System.out.println("user = " + user); return bundled == 0 || user == 0 || bundled > 0 && user > 0; } - @Override @NotNull - public List getSuggestions(@NotNull final String word, int threshold, int quality) { - final String transformed = transform.transform(word); - if (transformed == null) { - return Collections.emptyList(); - } - final List suggestions = new ArrayList(); - List rawSuggestions = restore(transformed.charAt(0), 0, Integer.MAX_VALUE, bundledDictionaries); - rawSuggestions.addAll(restore(word.charAt(0), 0, Integer.MAX_VALUE, dictionaries)); + public List getSuggestions(@NotNull String word, int maxSuggestions, int quality) { + String transformed = transform.transform(word); + if (transformed == null) return Collections.emptyList(); + + List rawSuggestions = new ArrayList(); + restore(transformed.charAt(0), 0, Integer.MAX_VALUE, bundledDictionaries, rawSuggestions); + restore(word.charAt(0), 0, Integer.MAX_VALUE, dictionaries, rawSuggestions); + if (rawSuggestions.isEmpty()) return Collections.emptyList(); + + List suggestions = new ArrayList(rawSuggestions.size()); for (String rawSuggestion : rawSuggestions) { int distance = EditDistance.levenshtein(transformed, rawSuggestion, true); suggestions.add(new Suggestion(rawSuggestion, distance)); } - List result = new ArrayList(); - if (suggestions.isEmpty()) { - return result; - } - Collections.sort(suggestions); - int bestMetrics = suggestions.get(0).getMetrics(); - for (int i = 0; i < threshold; i++) { - if (suggestions.size() <= i || bestMetrics - suggestions.get(i).getMetrics() > quality) { + Collections.sort(suggestions); + int limit = Math.min(maxSuggestions, suggestions.size()); + List result = new ArrayList(limit); + int bestMetrics = suggestions.get(0).getMetrics(); + for (int i = 0; i < limit; i++) { + Suggestion suggestion = suggestions.get(i); + if (bestMetrics - suggestion.getMetrics() > quality) { break; } - result.add(i, suggestions.get(i).getWord()); + result.add(i, suggestion.getWord()); } return result; } - @Override @NotNull public List getVariants(@NotNull String prefix) { - //if (StringUtil.isEmpty(prefix)) { return Collections.emptyList(); - //} - } @Override From 3901c9aa150358afde9c90700776a4fdefc5c4a7 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Sat, 13 Jun 2015 17:32:52 +0300 Subject: [PATCH 41/86] Cleanup (converted to JUnit 4; sole Groovy test migrated to Java) --- .../intellij/spellchecker/StreamLoader.java | 35 +-- .../inspections/BaseSplitter.java | 19 +- .../spellchecker/compress/DictionaryTest.java | 223 +++++++----------- .../compress/EncodeAndCompressTest.java | 45 ++-- .../spellchecker/compress/EncoderTest.java | 21 +- .../spellchecker/compress/UnitBitSetTest.java | 11 +- .../SpellcheckerPerformanceTest.groovy | 51 ---- .../SpellcheckerPerformanceTest.java | 59 +++++ .../spellchecker/inspector/SplitterTest.java | 137 ++++++----- .../inspector/SuggestionTest.java | 36 +-- .../SpellCheckingEditorCustomizationTest.java | 12 +- 11 files changed, 308 insertions(+), 341 deletions(-) delete mode 100644 spellchecker/testSrc/com/intellij/spellchecker/inspection/SpellcheckerPerformanceTest.groovy create mode 100644 spellchecker/testSrc/com/intellij/spellchecker/inspection/SpellcheckerPerformanceTest.java diff --git a/spellchecker/src/com/intellij/spellchecker/StreamLoader.java b/spellchecker/src/com/intellij/spellchecker/StreamLoader.java index e94a9e2d7036..276b7db388f6 100644 --- a/spellchecker/src/com/intellij/spellchecker/StreamLoader.java +++ b/spellchecker/src/com/intellij/spellchecker/StreamLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,15 +24,12 @@ import org.jetbrains.annotations.NotNull; import java.io.*; public class StreamLoader implements Loader { - - private static final Logger LOG = Logger.getInstance("#com.intellij.spellchecker.StreamLoader"); - private final InputStream stream; private final String name; public StreamLoader(InputStream stream, String name) { this.stream = stream; - this.name=name; + this.name = name; } @Override @@ -42,28 +39,20 @@ public class StreamLoader implements Loader { @Override public void load(@NotNull Consumer consumer) { - DataInputStream in = new DataInputStream(stream); - BufferedReader br = null; - try { - br = new BufferedReader(new InputStreamReader(in, CharsetToolkit.UTF8_CHARSET)); - String strLine; - while ((strLine = br.readLine()) != null) { - consumer.consume(strLine); + BufferedReader br = new BufferedReader(new InputStreamReader(stream, CharsetToolkit.UTF8_CHARSET)); + try { + String line; + while ((line = br.readLine()) != null) { + consumer.consume(line); + } + } + finally { + br.close(); } } catch (Exception e) { - LOG.error(e); - } - finally { - try { - br.close(); - } - catch (IOException ignored) { - - } + Logger.getInstance(StreamLoader.class).error(e); } } - } - diff --git a/spellchecker/src/com/intellij/spellchecker/inspections/BaseSplitter.java b/spellchecker/src/com/intellij/spellchecker/inspections/BaseSplitter.java index 1fa96afac5a2..57449292cb55 100644 --- a/spellchecker/src/com/intellij/spellchecker/inspections/BaseSplitter.java +++ b/spellchecker/src/com/intellij/spellchecker/inspections/BaseSplitter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ */ package com.intellij.spellchecker.inspections; -import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.util.TextRange; @@ -32,14 +32,9 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; - public abstract class BaseSplitter implements Splitter { - - static final Logger LOG = Logger.getInstance("#com.intellij.spellchecker.inspections.BaseSplitter"); - public static final int MIN_RANGE_LENGTH = 3; - protected static void addWord(@NotNull Consumer consumer, boolean ignore, @Nullable TextRange found) { if (found == null || ignore) { return; @@ -51,7 +46,6 @@ public abstract class BaseSplitter implements Splitter { consumer.consume(found); } - protected static boolean isAllWordsAreUpperCased(@NotNull String text, @NotNull List words) { for (TextRange word : words) { CharacterIterator it = new StringCharacterIterator(text, word.getStartOffset(), word.getEndOffset(), word.getStartOffset()); @@ -62,7 +56,6 @@ public abstract class BaseSplitter implements Splitter { } } return true; - } protected static boolean containsShortWord(@NotNull List words) { @@ -130,15 +123,13 @@ public abstract class BaseSplitter implements Splitter { return toCheck; } catch (ProcessCanceledException e) { - //LOG.warn("Matching took too long: >>>" + range.substring(text) + "<<< " + toExclude); return Collections.singletonList(range); - //return Collections.emptyList(); } } public static void checkCancelled() { - ProgressIndicatorProvider.checkCanceled(); + if (ApplicationManager.getApplication() != null) { + ProgressIndicatorProvider.checkCanceled(); + } } - - } diff --git a/spellchecker/testSrc/com/intellij/spellchecker/compress/DictionaryTest.java b/spellchecker/testSrc/com/intellij/spellchecker/compress/DictionaryTest.java index c2ce1d39c64a..ea623553325e 100644 --- a/spellchecker/testSrc/com/intellij/spellchecker/compress/DictionaryTest.java +++ b/spellchecker/testSrc/com/intellij/spellchecker/compress/DictionaryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,7 @@ package com.intellij.spellchecker.compress; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.util.Ref; import com.intellij.spellchecker.DefaultBundledDictionariesProvider; import com.intellij.spellchecker.StreamLoader; import com.intellij.spellchecker.dictionary.Dictionary; @@ -27,172 +26,128 @@ import com.intellij.testFramework.PlatformTestUtil; import com.intellij.util.Consumer; import com.intellij.util.ThrowableRunnable; import gnu.trove.THashSet; -import junit.framework.TestCase; import org.jetbrains.annotations.NotNull; +import org.junit.Test; -import java.io.File; -import java.io.IOException; -import java.util.*; +import java.util.Set; -@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"}) -public class DictionaryTest extends TestCase { +import static com.intellij.openapi.util.Pair.pair; +import static org.junit.Assert.*; - private Dictionary dictionary; - - private final Map sizes = new HashMap(); - private final Map times = new HashMap(); +public class DictionaryTest { private static final String JETBRAINS_DIC = "jetbrains.dic"; private static final String ENGLISH_DIC = "english.dic"; - { - sizes.put(JETBRAINS_DIC, 1000); - sizes.put(ENGLISH_DIC, 140000); + private final Transformation myTransformation = new Transformation(); + + @Test + public void testJBDictionary() { + Dictionary dictionary = loadDictionaryPerformanceTest(JETBRAINS_DIC, 1000); + containsWordPerformanceTest(dictionary, 2000); + containsWordTest(dictionary); } - { - times.put(JETBRAINS_DIC, 1000); - times.put(ENGLISH_DIC, 50000); - } - - public void testDictionary() throws IOException { - final String[] names = {JETBRAINS_DIC, ENGLISH_DIC}; - for (String name : names) { - loadDictionaryTest(name, sizes.get(name)); - loadHalfDictionaryTest(name, 50000); - } + @Test + public void testEnglishDictionary() { + Dictionary dictionary = loadDictionaryPerformanceTest(ENGLISH_DIC, 50000); + containsWordPerformanceTest(dictionary, 2000); + containsWordTest(dictionary); } + @Test public void testDictionaryLoadedFully() { - //cleanupDictionary(); - final Transformation transform = new Transformation(); - CompressedDictionary dictionary = CompressedDictionary.create(englishLoader(), transform); - final Set onDisk = new THashSet(); - englishLoader().load(new Consumer() { + getLoader(JETBRAINS_DIC).load(new Consumer() { @Override public void consume(String s) { - assert s != null; - String t = transform.transform(s); - if (t == null) { - return; + assertNotNull(s); + String t = myTransformation.transform(s); + if (t != null) { + onDisk.add(t); } - onDisk.add(t); } }); - List odList = new ArrayList(onDisk); - Collections.sort(odList); - List loaded = new ArrayList(dictionary.getWords()); - Collections.sort(loaded); + Dictionary dictionary = CompressedDictionary.create(getLoader(JETBRAINS_DIC), myTransformation); - assertEquals(odList, loaded); + assertEquals(onDisk, dictionary.getWords()); } - public void cleanupDictionary() { - final Set onDisk = new THashSet(FileUtil.PATH_HASHING_STRATEGY); - englishLoader().load(new Consumer() { + private Dictionary loadDictionaryPerformanceTest(final String name, int time) { + final Ref ref = Ref.create(); + + PlatformTestUtil.startPerformanceTest("load dictionary", time, new ThrowableRunnable() { @Override - public void consume(String s) { - assert s != null; - onDisk.add(s); - } - }); - - List odList = new ArrayList(onDisk); - Collections.sort(odList); - - File file = new File("C:\\Work\\Idea\\community\\spellchecker\\src\\com\\intellij\\spellchecker\\english.2"); - try { - FileUtil.writeToFile(file, StringUtil.join(odList, "\n")); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - - private static StreamLoader englishLoader() { - return new StreamLoader(DefaultBundledDictionariesProvider.class.getResourceAsStream(ENGLISH_DIC), ENGLISH_DIC); - } - - public void loadDictionaryTest(@NotNull final String name, int wordCount) throws IOException { - final Transformation transform = new Transformation(); - PlatformTestUtil.startPerformanceTest("load dictionary", times.get(name), new ThrowableRunnable() { - @Override - public void run() throws Exception { - dictionary = CompressedDictionary - .create(new StreamLoader(DefaultBundledDictionariesProvider.class.getResourceAsStream(name), name), transform); + public void run() { + ref.set(CompressedDictionary.create(getLoader(name), myTransformation)); } }).cpuBound().assertTiming(); - final Set wordsToStoreAndCheck = createWordSets(name, 50000, 1).getFirst(); - PlatformTestUtil.startPerformanceTest("words contain",2000, new ThrowableRunnable() { + assertFalse(ref.isNull()); + return ref.get(); + } + + private void containsWordPerformanceTest(final Dictionary dictionary, int time) { + final Set wordsToCheck = createWordSets(dictionary, 50000, 1).first; + PlatformTestUtil.startPerformanceTest("contains word", time, new ThrowableRunnable() { @Override - public void run() throws Exception { - for (String s : wordsToStoreAndCheck) { - assertTrue(dictionary.contains(s)); + public void run() { + for (String s : wordsToCheck) { + assertEquals(Boolean.TRUE, dictionary.contains(s)); } } }).cpuBound().assertTiming(); } - private static Loader createLoader(final Set words) { - return new Loader() { - @Override - public void load(@NotNull Consumer consumer) { - for (String word : words) { - consumer.consume(word); - } - } - - @Override - public String getName() { - return "test"; - } - }; - } - - @SuppressWarnings({"unchecked"}) - private static Pair, Set> createWordSets(String name, final int maxCount, final int mod) { - Loader loader = new StreamLoader(DefaultBundledDictionariesProvider.class.getResourceAsStream(name), name); - final Set wordsToStore = new THashSet(); - final Set wordsToCheck = new THashSet(); - final Transformation transform = new Transformation(); - loader.load(new Consumer() { - private int counter = 0; - - @Override - public void consume(String s) { - if (counter > maxCount) { - return; - } - String transformed = transform.transform(s); - if (transformed != null) { - - if (counter % mod == 0) { - wordsToStore.add(transformed); - } - else { - wordsToCheck.add(transformed); - } - counter++; - } - } - }); - - return new Pair(wordsToStore, wordsToCheck); - } - - - public static void loadHalfDictionaryTest(final String name, final int maxCount) { - final Pair, Set> sets = createWordSets(name, maxCount, 2); - final Loader loader = createLoader(sets.getFirst()); - CompressedDictionary dictionary = CompressedDictionary.create(loader, new Transformation()); - for (String s : sets.getSecond()) { - if (!sets.getFirst().contains(s)) { - assertFalse(s, dictionary.contains(s)); + private void containsWordTest(Dictionary dictionary) { + Pair, Set> sets = createWordSets(dictionary, 50000, 2); + CompressedDictionary half = CompressedDictionary.create(new TestLoader(sets.first), myTransformation); + for (String s : sets.second) { + if (!sets.first.contains(s)) { + assertEquals(s, Boolean.FALSE, half.contains(s)); } } } + private static StreamLoader getLoader(@NotNull String name) { + return new StreamLoader(DefaultBundledDictionariesProvider.class.getResourceAsStream(name), name); + } + private Pair, Set> createWordSets(Dictionary dictionary, int maxCount, int mod) { + Set wordsToStore = new THashSet(); + Set wordsToCheck = new THashSet(); + + Set words = dictionary.getWords(); + assertNotNull(words); + int counter = 0; + for (String s : words) { + String transformed = myTransformation.transform(s); + if (transformed != null) { + (counter % mod == 0 ? wordsToStore : wordsToCheck).add(transformed); + if (++counter > maxCount) break; + } + } + + return pair(wordsToStore, wordsToCheck); + } + + private static class TestLoader implements Loader { + private final Set myWords; + + public TestLoader(Set words) { + myWords = words; + } + + @Override + public void load(@NotNull Consumer consumer) { + for (String word : myWords) { + consumer.consume(word); + } + } + + @Override + public String getName() { + return "test"; + } + } } diff --git a/spellchecker/testSrc/com/intellij/spellchecker/compress/EncodeAndCompressTest.java b/spellchecker/testSrc/com/intellij/spellchecker/compress/EncodeAndCompressTest.java index 96d70d802d70..9195a4c6e48e 100644 --- a/spellchecker/testSrc/com/intellij/spellchecker/compress/EncodeAndCompressTest.java +++ b/spellchecker/testSrc/com/intellij/spellchecker/compress/EncodeAndCompressTest.java @@ -1,19 +1,36 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.spellchecker.compress; -import junit.framework.TestCase; +import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; -public class EncodeAndCompressTest extends TestCase { - - public void testEncodeAndCompress() { - Encoder encoder = new Encoder(); - String word = "example"; - UnitBitSet bs = encoder.encode(word, true); - byte[] compressed = bs.pack(); - final String decompressed = UnitBitSet.decode(compressed, encoder.getAlphabet()); - assertEquals(word,decompressed); - String restored = encoder.decode(compressed); - assertEquals(word,restored); - } - +public class EncodeAndCompressTest { + @Test + public void testEncodeAndCompress() { + Encoder encoder = new Encoder(); + String word = "example"; + UnitBitSet bs = encoder.encode(word, true); + assertNotNull(bs); + byte[] compressed = bs.pack(); + String decompressed = UnitBitSet.decode(compressed, encoder.getAlphabet()); + assertEquals(word, decompressed); + String restored = encoder.decode(compressed); + assertEquals(word, restored); + } } diff --git a/spellchecker/testSrc/com/intellij/spellchecker/compress/EncoderTest.java b/spellchecker/testSrc/com/intellij/spellchecker/compress/EncoderTest.java index 1c90ddf0a6dd..8ad5e79847c9 100644 --- a/spellchecker/testSrc/com/intellij/spellchecker/compress/EncoderTest.java +++ b/spellchecker/testSrc/com/intellij/spellchecker/compress/EncoderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,13 @@ */ package com.intellij.spellchecker.compress; -import junit.framework.TestCase; +import org.junit.Test; -public class EncoderTest extends TestCase { +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertEquals; + +public class EncoderTest { + @Test public void testSimple() { Encoder encoder = new Encoder(); final String wordToTest = "abc"; @@ -37,7 +41,7 @@ public class EncoderTest extends TestCase { } } - + @Test public void testDouble() { Encoder encoder = new Encoder(); final String wordToTest = "aaa"; @@ -49,6 +53,7 @@ public class EncoderTest extends TestCase { assertEquals(wordToTest, encoder.decode(bitSet.pack())); } + @Test public void testLetterRepetition() { Encoder encoder = new Encoder(); final String wordToTest = "aba"; @@ -60,6 +65,7 @@ public class EncoderTest extends TestCase { assertEquals(wordToTest, encoder.decode(bitSet.pack())); } + @Test public void testReverse() { Encoder encoder = new Encoder(); final String wordToTest1 = "abc"; @@ -83,19 +89,20 @@ public class EncoderTest extends TestCase { assertEquals(wordToTest2, encoder.decode(pack2)); } - + @Test public void testWithPredefinedAlphabet() { - Encoder encoder = new Encoder(new Alphabet("abcdefghijklmnopqrst")); + @SuppressWarnings("SpellCheckingInspection") Encoder encoder = new Encoder(new Alphabet("abcdefghijklmnopqrst")); final String wordToTest1 = "asia"; //letter 'a' will be added at the end final UnitBitSet bitSet = encoder.encode(wordToTest1, true); assertNotNull(bitSet); assertEquals(20, encoder.getAlphabet().getLastIndexUsed()); - assertIndices(bitSet, 1, 19, 9,1); + assertIndices(bitSet, 1, 19, 9, 1); assertEquals(wordToTest1, encoder.decode(bitSet.pack())); } + @Test public void testUnknown() { Encoder encoder = new Encoder(new Alphabet("abc")); final String wordToTest1 = "def"; diff --git a/spellchecker/testSrc/com/intellij/spellchecker/compress/UnitBitSetTest.java b/spellchecker/testSrc/com/intellij/spellchecker/compress/UnitBitSetTest.java index a4f6e2c4f310..be332bb395a6 100644 --- a/spellchecker/testSrc/com/intellij/spellchecker/compress/UnitBitSetTest.java +++ b/spellchecker/testSrc/com/intellij/spellchecker/compress/UnitBitSetTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,10 +15,12 @@ */ package com.intellij.spellchecker.compress; -import junit.framework.TestCase; +import org.junit.Test; -public class UnitBitSetTest extends TestCase { +import static org.junit.Assert.assertEquals; +public class UnitBitSetTest { + @Test public void testUnitValue() { int bitsPerUnit = 256; for (int i = 0; i < bitsPerUnit - 1; i++) { @@ -28,7 +30,4 @@ public class UnitBitSetTest extends TestCase { assertEquals(0, bs.getUnitValue(1)); } } - - - } diff --git a/spellchecker/testSrc/com/intellij/spellchecker/inspection/SpellcheckerPerformanceTest.groovy b/spellchecker/testSrc/com/intellij/spellchecker/inspection/SpellcheckerPerformanceTest.groovy deleted file mode 100644 index 87562183c66d..000000000000 --- a/spellchecker/testSrc/com/intellij/spellchecker/inspection/SpellcheckerPerformanceTest.groovy +++ /dev/null @@ -1,51 +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.spellchecker.inspection - -import com.intellij.testFramework.PlatformTestUtil -/** - * @author peter - */ -public class SpellcheckerPerformanceTest extends SpellcheckerInspectionTestCase { - @Override - protected void setUp() throws Exception { - def start = System.currentTimeMillis() - super.setUp() - println("setUp took " + (System.currentTimeMillis() - start)) - } - - public void "test large text file with many typos"() { - int typoCount = 50000 - String text = "aaaaaaaaa " * typoCount // about 0.5M - - def start = System.currentTimeMillis() - def file = myFixture.addFileToProject("foo.txt", text).virtualFile - println("creation took " + (System.currentTimeMillis() - start)) - - start = System.currentTimeMillis() - myFixture.configureFromExistingVirtualFile(file) - println("configure took " + (System.currentTimeMillis() - start)) - - myFixture.enableInspections(inspectionTools) - - start = System.currentTimeMillis() - assertSize(typoCount, myFixture.doHighlighting()) - println("warmup took " + (System.currentTimeMillis() - start)) - - PlatformTestUtil.assertTiming("highlighting too long", 1000) { assertSize(typoCount, myFixture.doHighlighting()) } - } - -} diff --git a/spellchecker/testSrc/com/intellij/spellchecker/inspection/SpellcheckerPerformanceTest.java b/spellchecker/testSrc/com/intellij/spellchecker/inspection/SpellcheckerPerformanceTest.java new file mode 100644 index 000000000000..a1f19ea53d34 --- /dev/null +++ b/spellchecker/testSrc/com/intellij/spellchecker/inspection/SpellcheckerPerformanceTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.spellchecker.inspection; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.util.ThrowableRunnable; + +/** + * @author peter + */ +public class SpellcheckerPerformanceTest extends SpellcheckerInspectionTestCase { + @Override + protected void setUp() throws Exception { + long start = System.currentTimeMillis(); + super.setUp(); + System.out.println("setUp took " + (System.currentTimeMillis() - start) + " ms"); + } + + public void testLargeTextFileWithManyTypos() { + final int typoCount = 50000; + @SuppressWarnings("SpellCheckingInspection") String text = StringUtil.repeat("aaaaaaaaa ", typoCount); // about 0.5M + + long start = System.currentTimeMillis(); + VirtualFile file = myFixture.addFileToProject("foo.txt", text).getVirtualFile(); + System.out.println("creation took " + (System.currentTimeMillis() - start) + " ms"); + + start = System.currentTimeMillis(); + myFixture.configureFromExistingVirtualFile(file); + System.out.println("configure took " + (System.currentTimeMillis() - start) + " ms"); + + myFixture.enableInspections(getInspectionTools()); + + start = System.currentTimeMillis(); + assertSize(typoCount, myFixture.doHighlighting()); + System.out.println("warm-up took " + (System.currentTimeMillis() - start) + " ms"); + + PlatformTestUtil.startPerformanceTest("many typos highlighting", 1000, new ThrowableRunnable() { + @Override + public void run() { + assertSize(typoCount, myFixture.doHighlighting()); + } + }).cpuBound().assertTiming(); + } +} diff --git a/spellchecker/testSrc/com/intellij/spellchecker/inspector/SplitterTest.java b/spellchecker/testSrc/com/intellij/spellchecker/inspector/SplitterTest.java index 3562a59e2a8f..6f26abecf4ab 100644 --- a/spellchecker/testSrc/com/intellij/spellchecker/inspector/SplitterTest.java +++ b/spellchecker/testSrc/com/intellij/spellchecker/inspector/SplitterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,136 +18,154 @@ package com.intellij.spellchecker.inspector; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.spellchecker.inspections.*; -import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import com.intellij.util.Consumer; -import junit.framework.Assert; import org.jetbrains.annotations.NotNull; +import org.junit.Test; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import static org.junit.Assert.assertEquals; -public class SplitterTest extends LightPlatformCodeInsightFixtureTestCase { +@SuppressWarnings("SpellCheckingInspection") +public class SplitterTest { + @Test public void testSplitSimpleCamelCase() { String text = "simpleCamelCase"; correctListToCheck(IdentifierSplitter.getInstance(), text, "simple", "Camel", "Case"); } + @Test public void testSplitCamelCaseWithUpperCasedWord() { String text = "camelCaseJSP"; correctListToCheck(IdentifierSplitter.getInstance(), text, "camel", "Case"); } + @Test public void testArrays() { String text = "Token[]"; correctListToCheck(IdentifierSplitter.getInstance(), text, "Token"); } + @Test public void testIdentifierInSingleQuotes() { String text = "'fill'"; correctListToCheck(IdentifierSplitter.getInstance(), text, "fill"); } - + @Test public void testWordsInSingleQuotesWithSep() { String text = "'test-something'"; correctListToCheck(PlainTextSplitter.getInstance(), text, "test", "something"); } + @Test public void testComplexWordsInQuotes() { String text = "\"test-customer's'\""; correctListToCheck(PlainTextSplitter.getInstance(), text, "test", "customer's"); } + @Test public void testCapitalizedWithShortWords() { String text = "IntelliJ"; correctListToCheck(IdentifierSplitter.getInstance(), text, "Intelli"); } + @Test public void testWords() { String text = "first-last"; correctListToCheck(IdentifierSplitter.getInstance(), text, "first", "last"); } + @Test public void testCapitalizedWithShortAndLongWords() { String text = "IntelliJTestTest"; correctListToCheck(IdentifierSplitter.getInstance(), text, "Intelli", "Test", "Test"); } + @Test public void testWordWithApostrophe1() { String text = "don't check"; correctListToCheck(PlainTextSplitter.getInstance(), text, "don't", "check"); } + @Test public void testHexInPlainText() { String text = "some text 0xacvfgt"; correctListToCheck(PlainTextSplitter.getInstance(), text, "some", "text"); } + @Test public void testHexInStringLiteral() { String text = "qwerty 0x12acfgt test"; correctListToCheck(PlainTextSplitter.getInstance(), text, "qwerty", "test"); } - + @Test public void testHex() { String text = "0xacvfgt"; correctListToCheck(WordSplitter.getInstance(), text); } + @Test public void testCheckXmlIgnored() { String text = "abcdef" + new String(new char[]{0xDC00}) + "test"; correctListToCheck(PlainTextSplitter.getInstance(), text); } - public void testIdentifiersWithNumbers() { + @Test + public void testIdentifiersWithNumbers() { String text = "result1"; - correctListToCheck(IdentifierSplitter.getInstance(), text, "result"); + correctListToCheck(IdentifierSplitter.getInstance(), text, "result"); } + @Test public void testIdentifiersWithNumbersInside() { String text = "result1result"; - correctListToCheck(IdentifierSplitter.getInstance(), text, "result","result"); + correctListToCheck(IdentifierSplitter.getInstance(), text, "result", "result"); } + @Test public void testWordWithApostrophe2() { String text = "customers'"; correctListToCheck(PlainTextSplitter.getInstance(), text, "customers"); } + @Test public void testWordWithApostrophe3() { String text = "customer's"; correctListToCheck(PlainTextSplitter.getInstance(), text, "customer's"); } - + @Test public void testWordWithApostrophe4() { String text = "we'll"; correctListToCheck(PlainTextSplitter.getInstance(), text, "we'll"); } + @Test public void testWordWithApostrophe5() { String text = "I'm you're we'll"; correctListToCheck(PlainTextSplitter.getInstance(), text, "you're", "we'll"); } + @Test public void testConstantName() { String text = "TEST_CONSTANT"; correctListToCheck(IdentifierSplitter.getInstance(), text, "TEST", "CONSTANT"); - } + @Test public void testLongConstantName() { String text = "TEST_VERY_VERY_LONG_AND_COMPLEX_CONSTANT"; correctListToCheck(IdentifierSplitter.getInstance(), text, "TEST", "VERY", "VERY", "LONG", "COMPLEX", "CONSTANT"); - } + @Test public void testJavaComments() { String text = "/*special symbols*/"; correctListToCheck(CommentSplitter.getInstance(), text, "special", "symbols"); @@ -157,203 +175,207 @@ public class SplitterTest extends LightPlatformCodeInsightFixtureTestCase { text = "// comment line which spell check not works: misttake"; correctListToCheck(CommentSplitter.getInstance(), text, "comment", "line", "which", "spell", "check", "works", "misttake"); - } - + @Test public void testXmlComments() { String text = ""; correctListToCheck(CommentSplitter.getInstance(), text, "special", "symbols"); - } + @Test public void testCamelCaseInXmlComments() { String text = ""; correctListToCheck(CommentSplitter.getInstance(), text, "special", "Case", "symbols"); - } + @Test public void testWordsWithNumbers() { String text = "testCamelCase123"; correctListToCheck(IdentifierSplitter.getInstance(), text, "test", "Camel", "Case"); - } + @Test public void testCommentsWithWordsWithNumbers() { String text = ""; correctListToCheck(CommentSplitter.getInstance(), text, "special", "Case", "symbols"); - } + @Test public void testCommentsWithAbr() { String text = ""; correctListToCheck(CommentSplitter.getInstance(), text, "Test", "Class"); - } + @Test public void testStringLiterals() { String text = "test\ntest\n"; correctListToCheck(PlainTextSplitter.getInstance(), text, "test", "test"); - } - + @Test public void testCommentWithHtml() { String text = ""; - correctListToCheck(CommentSplitter.getInstance(), text, "something", "here", "next", "content", "foooo", "barrrr", - "text"); - + correctListToCheck(CommentSplitter.getInstance(), text, "something", "here", "next", "content", "foooo", "barrrr", "text"); } + @Test public void testCommentWithHtmlTagsAndAtr() { String text = ""; correctListToCheck(CommentSplitter.getInstance(), text, "something", "here", "foooo", "barrrr", "text", "text"); - } + @Test public void testSpecial() { String text = "test   test"; correctListToCheck(PlainTextSplitter.getInstance(), text, "test", "test"); - } + @Test public void testColorUC() { String text = "#AABBFF"; correctListToCheck(WordSplitter.getInstance(), text); - } + @Test public void testColorUCSC() { String text = "#AABBFF;"; correctListToCheck(WordSplitter.getInstance(), text); - } + @Test public void testColorUCSurrounded() { String text = "\"#AABBFF\""; correctListToCheck(WordSplitter.getInstance(), text); - } + @Test public void testColorLC() { String text = "#fff"; correctListToCheck(TextSplitter.getInstance(), text); - } + @Test public void testTooShort() { String text = "bgColor carLight"; correctListToCheck(PlainTextSplitter.getInstance(), text, "Color", "Light"); - } + @Test public void testPhpVariableCorrectSimple() { String text = "$this"; correctListToCheck(IdentifierSplitter.getInstance(), text, "this"); - } + @Test public void testPhpVariableCorrect() { String text = "$this_this$this"; correctListToCheck(IdentifierSplitter.getInstance(), text, "this", "this", "this"); - } + @Test public void testEmail() { String text = "some text with email (shkate.test@gmail.com) inside"; correctListToCheck(PlainTextSplitter.getInstance(), text, "some", "text", "with", "email", "inside"); - } + @Test public void testEmailOnly() { String text = "shkate123-\u00DC.test@gmail.com"; correctListToCheck(PlainTextSplitter.getInstance(), text); - } + @Test public void testUrl() { String text = "https://www.jetbrains.com/idea"; correctListToCheck(PlainTextSplitter.getInstance(), text); } + @Test public void testUrlThenSpaces() { String text = "https://www.jetbrains.com/idea asdasdasd sdfsdf"; correctListToCheck(PlainTextSplitter.getInstance(), text, "asdasdasd", "sdfsdf"); } + @Test public void testWordBeforeDelimiter() { String text = "badd,"; correctListToCheck(PlainTextSplitter.getInstance(), text, "badd"); } + @Test public void testWordAfterDelimiter() { String text = ",badd"; correctListToCheck(PlainTextSplitter.getInstance(), text, "badd"); } + @Test public void testWordInCapsBeforeDelimiter() { String text = "BADD,"; correctListToCheck(PlainTextSplitter.getInstance(), text, "BADD"); - } + @Test public void testWordInCapsAfterDelimiter() { String text = ",BADD"; correctListToCheck(PlainTextSplitter.getInstance(), text, "BADD"); - } + @Test public void testWordInCapsAfterDelimiter2() { String text = "BADD;"; correctListToCheck(PlainTextSplitter.getInstance(), text, "BADD"); - } + @Test public void testWordInCapsAfterDelimiter3() { String text = ";BADD;"; correctListToCheck(PlainTextSplitter.getInstance(), text, "BADD"); } + @Test public void testWordWithUmlauts() { String text = "rechtsb\u00FCndig"; correctListToCheck(PlainTextSplitter.getInstance(), text, text); } + @Test public void testWordUpperCasedWithUmlauts() { String text = "RECHTSB\u00DCNDIG"; correctListToCheck(PlainTextSplitter.getInstance(), text, text); } + @Test public void testCommaSeparatedList() { String text = "properties,test,properties"; correctListToCheck(PlainTextSplitter.getInstance(), text, "properties", "test", "properties"); - } + @Test public void testSemicolonSeparatedList() { String text = "properties;test;properties"; correctListToCheck(PlainTextSplitter.getInstance(), text, "properties", "test", "properties"); - } + @Test public void testProperties1() { String text = "properties.test.properties"; correctListToCheck(PropertiesSplitter.getInstance(), text, "properties", "test", "properties"); } - + @Test public void testPropertiesWithCamelCase() { String text = "upgrade.testCommit.propertiesSomeNews"; - correctListToCheck(PropertiesSplitter.getInstance(), text, "upgrade", "test", "Commit", "properties", "Some", - "News"); + correctListToCheck(PropertiesSplitter.getInstance(), text, "upgrade", "test", "Commit", "properties", "Some", "News"); } + @Test public void testWordUpperCasedWithUmlautsInTheBeginning() { String text = "\u00DCNDIG"; correctListToCheck(PlainTextSplitter.getInstance(), text, text); } - + @Test public void testTCData() { final InputStream stream = SplitterTest.class.getResourceAsStream("contents.txt"); String text = convertStreamToString(stream); @@ -361,7 +383,6 @@ public class SplitterTest extends LightPlatformCodeInsightFixtureTestCase { assertEquals(0, words.size()); } - private static List wordsToCheck(Splitter splitter, final String text) { final List words = new ArrayList(); splitter.split(text, TextRange.allOf(text), new Consumer() { @@ -373,36 +394,32 @@ public class SplitterTest extends LightPlatformCodeInsightFixtureTestCase { return words; } - private static void correctListToCheck(Splitter splitter, String text, @NotNull String... expected) { List words = wordsToCheck(splitter, text); List expectedWords = Arrays.asList(expected); - Assert.assertEquals("Splitting:'" + text + "'", expectedWords.toString(), words!=null ? words.toString() : "[]"); + assertEquals("Splitting:'" + text + "'", expectedWords.toString(), words != null ? words.toString() : "[]"); } - - private String convertStreamToString(InputStream is) { + private static String convertStreamToString(InputStream is) { if (is != null) { StringBuilder sb = new StringBuilder(); - String line; try { BufferedReader reader = new BufferedReader(new InputStreamReader(is, CharsetToolkit.UTF8_CHARSET)); - while ((line = reader.readLine()) != null) { - sb.append(line).append("\n"); + try { + String line; + while ((line = reader.readLine()) != null) { + sb.append(line).append('\n'); + } + } + finally { + reader.close(); } } catch (Exception e) { throw new RuntimeException(e); } - finally { - try { - is.close(); - } - catch (IOException ignore) { - } - } return sb.toString(); } else { diff --git a/spellchecker/testSrc/com/intellij/spellchecker/inspector/SuggestionTest.java b/spellchecker/testSrc/com/intellij/spellchecker/inspector/SuggestionTest.java index 552e3eb22976..eba7304505f2 100644 --- a/spellchecker/testSrc/com/intellij/spellchecker/inspector/SuggestionTest.java +++ b/spellchecker/testSrc/com/intellij/spellchecker/inspector/SuggestionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,34 +20,14 @@ import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCa import java.util.List; - +@SuppressWarnings("SpellCheckingInspection") public class SuggestionTest extends LightPlatformCodeInsightFixtureTestCase { + public void testSuggestions() { doTest("upgade", "upgrade"); } + public void testFirstLetterUppercaseSuggestions() { doTest("Upgade", "Upgrade"); } + public void testCamelCaseSuggestions() { doTest("TestUpgade", "TestUpgrade"); } - private SpellCheckerManager spManager; - - private SpellCheckerManager getManager() { - if (spManager == null) { - spManager = SpellCheckerManager.getInstance(myFixture.getProject()); - } - assert spManager != null; - return spManager; - } - - public void testSuggestions() { - List result = getManager().getSuggestions("upgade"); - assertEquals("upgrade", result.get(0)); - } - - - public void testFirstLetterUppercaseSuggestions() { - List result = getManager().getSuggestions("Upgade"); - assertEquals("Upgrade", result.get(0)); - } - - public void testCamelCaseSuggestions() { - SpellCheckerManager manager = SpellCheckerManager.getInstance(myFixture.getProject()); - assert manager != null; - List result = manager.getSuggestions("TestUpgade"); - assertEquals("TestUpgrade", result.get(0)); + private void doTest(String word, String expected) { + List result = SpellCheckerManager.getInstance(myFixture.getProject()).getSuggestions(word); + assertEquals(expected, result.get(0)); } } diff --git a/spellchecker/testSrc/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationTest.java b/spellchecker/testSrc/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationTest.java index 32efe07e71b0..679b32f72f90 100644 --- a/spellchecker/testSrc/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationTest.java +++ b/spellchecker/testSrc/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,13 +22,15 @@ import com.intellij.openapi.fileTypes.PlainTextFileType; import com.intellij.spellchecker.inspections.SpellCheckingInspection; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl; +import com.intellij.ui.EditorCustomization; +@SuppressWarnings("SpellCheckingInspection") public class SpellCheckingEditorCustomizationTest extends LightPlatformCodeInsightFixtureTestCase { - public void testEnabled() throws Exception { + public void testEnabled() { doTest(true, "missspelling"); } - public void testDisabled() throws Exception { + public void testDisabled() { doTest(false, "missspelling"); } @@ -48,7 +50,9 @@ public class SpellCheckingEditorCustomizationTest extends LightPlatformCodeInsig myFixture.configureByText(PlainTextFileType.INSTANCE, document); myFixture.enableInspections(new SpellCheckingInspection()); - SpellCheckingEditorCustomizationProvider.getInstance().getCustomization(enabled).customize((EditorEx)myFixture.getEditor()); + EditorCustomization customization = SpellCheckingEditorCustomizationProvider.getInstance().getCustomization(enabled); + assertNotNull(customization); + customization.customize((EditorEx)myFixture.getEditor()); myFixture.checkHighlighting(); } From 25053738f5fab62d2aa7f07797d0812b4e4ebfb1 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 11 Jun 2015 15:37:38 +0300 Subject: [PATCH 42/86] IDEA-118080 (ability to define custom headers for inspection) --- java/manifest/manifest.iml | 4 +- .../lang/manifest/ManifestBundle.properties | 5 +- .../lang/manifest/header/HeaderNameMatch.java | 81 ---------- .../header/HeaderParserRepository.java | 25 +--- .../AbstractManifestQuickFix.java | 33 ++++ .../MissingFinalNewlineInspection.java | 8 +- .../MisspelledHeaderInspection.java | 141 ++++++++++++++---- .../lang/manifest/ManifestPsiTest.java | 27 ++-- .../MisspelledHeaderInspectionTest.java | 52 ++++++- 9 files changed, 212 insertions(+), 164 deletions(-) delete mode 100644 java/manifest/src/org/jetbrains/lang/manifest/header/HeaderNameMatch.java create mode 100644 java/manifest/src/org/jetbrains/lang/manifest/highlighting/AbstractManifestQuickFix.java diff --git a/java/manifest/manifest.iml b/java/manifest/manifest.iml index 1c394ddffd93..212982b8ac5c 100644 --- a/java/manifest/manifest.iml +++ b/java/manifest/manifest.iml @@ -17,6 +17,6 @@ + - - + \ No newline at end of file diff --git a/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.properties b/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.properties index 845c88d11741..7fe98d7431e7 100644 --- a/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.properties +++ b/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.properties @@ -1,4 +1,3 @@ -manifest.unexpected.token=Unexpected token manifest.colon.expected=':' expected manifest.whitespace.expected=Whitespace expected manifest.header.expected=Header expected @@ -11,4 +10,6 @@ inspection.group=Manifest inspection.newline.message=Manifest file doesn't end with a final newline inspection.newline.fix=Add newline inspection.header.message=Header name is unknown or spelled incorrectly -inspection.header.fix=Change to ''{0}'' +inspection.header.ui.label=Custom headers: +inspection.header.rename.fix=Change to ''{0}'' +inspection.header.remember.fix=Add ''{0}'' to custom headers diff --git a/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderNameMatch.java b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderNameMatch.java deleted file mode 100644 index 8ab3669ac539..000000000000 --- a/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderNameMatch.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2007-2009, Osmorc Development Team - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * * Neither the name of 'Osmorc Development Team' nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package org.jetbrains.lang.manifest.header; - -import org.jetbrains.annotations.NotNull; - -/** - * A match describes how good a header known to a particular header provider matches a given header. - * The name of the given header may contain typos and so there may be no perfect match. A perfect match will - * have a Levenshtein distance of 0. Worse matches will have greater Levenshtein distances. - * - * @author Robert F. Beeger (robert@beeger.net) - */ -public class HeaderNameMatch implements Comparable { - private final int myDistance; - private final String myHeaderName; - - public HeaderNameMatch(int distance, @NotNull String headerName) { - myDistance = distance; - myHeaderName = headerName; - } - - public int getDistance() { - return myDistance; - } - - public String getHeaderName() { - return myHeaderName; - } - - /** - * Matches are compared based on their distance. - */ - @Override - public int compareTo(@NotNull HeaderNameMatch o) { - return getDistance() - o.getDistance(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - - HeaderNameMatch that = (HeaderNameMatch)o; - - return myDistance == that.myDistance && myHeaderName.equals(that.myHeaderName); - } - - @Override - public int hashCode() { - int result = myDistance; - result = 31 * result + myHeaderName.hashCode(); - return result; - } -} diff --git a/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParserRepository.java b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParserRepository.java index 27b80df35e1e..caab71dbf65a 100644 --- a/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParserRepository.java +++ b/java/manifest/src/org/jetbrains/lang/manifest/header/HeaderParserRepository.java @@ -27,19 +27,17 @@ package org.jetbrains.lang.manifest.header; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.NotNullLazyValue; -import com.intellij.openapi.util.text.LevenshteinDistance; import com.intellij.psi.PsiReference; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.text.CaseInsensitiveStringHashingStrategy; +import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.lang.manifest.psi.Header; import org.jetbrains.lang.manifest.psi.HeaderValuePart; -import java.util.Collection; import java.util.Map; import java.util.Set; -import java.util.TreeSet; /** * @author Robert F. Beeger (robert@beeger.net) @@ -53,7 +51,7 @@ public class HeaderParserRepository { @NotNull @Override protected Map compute() { - Map map = ContainerUtil.newHashMap(); + Map map = new THashMap(CaseInsensitiveStringHashingStrategy.INSTANCE); for (HeaderParserProvider provider : Extensions.getExtensions(HeaderParserProvider.EP_NAME)) { map.putAll(provider.getHeaderParsers()); } @@ -66,23 +64,6 @@ public class HeaderParserRepository { return myParsers.getValue().get(headerName); } - @NotNull - public Collection getMatches(@NotNull String headerName) { - HeaderParser parser = myParsers.getValue().get(headerName); - if (parser != null) { - return ContainerUtil.emptyList(); - } - - LevenshteinDistance distance = new LevenshteinDistance(); - Set result = new TreeSet(); - for (Map.Entry entry : myParsers.getValue().entrySet()) { - String otherName = entry.getKey(); - int dist = distance.calculateMetrics(headerName, otherName); - result.add(new HeaderNameMatch(dist, otherName)); - } - return result; - } - @NotNull public Set getAllHeaderNames() { return myParsers.getValue().keySet(); diff --git a/java/manifest/src/org/jetbrains/lang/manifest/highlighting/AbstractManifestQuickFix.java b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/AbstractManifestQuickFix.java new file mode 100644 index 000000000000..c548ff918d1a --- /dev/null +++ b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/AbstractManifestQuickFix.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.lang.manifest.highlighting; + +import com.intellij.codeInspection.LocalQuickFixOnPsiElement; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.lang.manifest.ManifestBundle; + +public abstract class AbstractManifestQuickFix extends LocalQuickFixOnPsiElement { + protected AbstractManifestQuickFix(@NotNull PsiElement element) { + super(element); + } + + @NotNull + @Override + public final String getFamilyName() { + return ManifestBundle.message("inspection.group"); + } +} diff --git a/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MissingFinalNewlineInspection.java b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MissingFinalNewlineInspection.java index 60bfce5fd13c..3bdf451f8623 100644 --- a/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MissingFinalNewlineInspection.java +++ b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MissingFinalNewlineInspection.java @@ -61,7 +61,7 @@ public class MissingFinalNewlineInspection extends LocalInspectionTool { return null; } - private static class AddNewlineQuickFix extends LocalQuickFixOnPsiElement { + private static class AddNewlineQuickFix extends AbstractManifestQuickFix { private AddNewlineQuickFix(Section section) { super(section); } @@ -72,12 +72,6 @@ public class MissingFinalNewlineInspection extends LocalInspectionTool { return ManifestBundle.message("inspection.newline.fix"); } - @NotNull - @Override - public String getFamilyName() { - return ManifestBundle.message("inspection.group"); - } - @Override public void invoke(@NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { PsiElement lastChild = startElement.getLastChild(); diff --git a/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MisspelledHeaderInspection.java b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MisspelledHeaderInspection.java index 75f41764fe5c..98065392b352 100644 --- a/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MisspelledHeaderInspection.java +++ b/java/manifest/src/org/jetbrains/lang/manifest/highlighting/MisspelledHeaderInspection.java @@ -26,25 +26,42 @@ package org.jetbrains.lang.manifest.highlighting; import com.intellij.codeInspection.*; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.profile.codeInspection.InspectionProfileManager; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiFile; +import com.intellij.spellchecker.engine.Suggestion; +import com.intellij.ui.DocumentAdapter; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.text.CaseInsensitiveStringHashingStrategy; +import com.intellij.util.text.EditDistance; +import com.intellij.util.xmlb.annotations.AbstractCollection; +import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.lang.manifest.ManifestBundle; -import org.jetbrains.lang.manifest.header.HeaderNameMatch; import org.jetbrains.lang.manifest.header.HeaderParserRepository; import org.jetbrains.lang.manifest.psi.Header; -import java.util.Collection; +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import java.awt.*; +import java.util.*; import java.util.List; /** * @author Robert F. Beeger (robert@beeger.net) */ public class MisspelledHeaderInspection extends LocalInspectionTool { - private static final int MAX_SUGGESTIONS = 10; + private static final int MAX_SUGGESTIONS = 5; + private static final int MAX_DISTANCE = 4; + private static final int TYPO_DISTANCE = 2; - private HeaderParserRepository myRepository; + @AbstractCollection(surroundWithTag = false, elementTag = "header") + public final Set CUSTOM_HEADERS = new THashSet(CaseInsensitiveStringHashingStrategy.INSTANCE); + + private final HeaderParserRepository myRepository; public MisspelledHeaderInspection() { myRepository = HeaderParserRepository.getInstance(); @@ -58,49 +75,117 @@ public class MisspelledHeaderInspection extends LocalInspectionTool { public void visitElement(PsiElement element) { if (element instanceof Header) { Header header = (Header)element; - Collection matches = myRepository.getMatches(header.getName()); - if (!matches.isEmpty()) { - List fixes = ContainerUtil.newArrayListWithCapacity(MAX_SUGGESTIONS); - for (HeaderNameMatch match : matches) { - fixes.add(new HeaderNameSpellingQuickFix(header, match)); - if (fixes.size() == MAX_SUGGESTIONS) { - break; - } - } - holder.registerProblem( - header.getNameElement(), ManifestBundle.message("inspection.header.message"), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fixes.toArray(new HeaderNameSpellingQuickFix[fixes.size()]) - ); + String headerName = header.getName(); + + SortedSet matches = new TreeSet(); + addMatches(headerName, CUSTOM_HEADERS, matches); + addMatches(headerName, myRepository.getAllHeaderNames(), matches); + + Suggestion bestMatch = ContainerUtil.getFirstItem(matches); + if (bestMatch != null && headerName.equals(bestMatch.getWord())) { + return; + } + + List fixes = new ArrayList(); + for (Suggestion match : matches) { + fixes.add(new HeaderRenameQuickFix(header, match.getWord())); + if (fixes.size() == MAX_SUGGESTIONS) break; + } + if (bestMatch == null || bestMatch.getMetrics() > TYPO_DISTANCE) { + fixes.add(new CustomHeaderQuickFix(header, CUSTOM_HEADERS)); + } + holder.registerProblem( + header.getNameElement(), ManifestBundle.message("inspection.header.message"), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fixes.toArray(new LocalQuickFix[fixes.size()]) + ); + } + } + + private void addMatches(String headerName, Collection headers, SortedSet matches) { + for (String candidate : headers) { + int distance = EditDistance.optimalAlignment(headerName, candidate, false); + if (distance <= MAX_DISTANCE) { + matches.add(new Suggestion(candidate, distance)); } } } }; } - private static class HeaderNameSpellingQuickFix implements LocalQuickFix { - private final Header myHeader; + @Override + public JComponent createOptionsPanel() { + return new OptionsPanel(CUSTOM_HEADERS); + } + + private static class OptionsPanel extends JPanel { + public OptionsPanel(final Set headers) { + super(new BorderLayout(5, 5)); + + add(new JLabel(ManifestBundle.message("inspection.header.ui.label")), BorderLayout.NORTH); + + final JTextArea area = new JTextArea(""); + add(area, BorderLayout.CENTER); + if (!headers.isEmpty()) { + area.setText(StringUtil.join(new TreeSet(headers), "\n")); + } + + area.getDocument().addDocumentListener(new DocumentAdapter() { + @Override + protected void textChanged(DocumentEvent e) { + headers.clear(); + for (String line : StringUtil.split(area.getText(), "\n")) { + String header = line.trim(); + if (!header.isEmpty()) { + headers.add(header); + } + } + } + }); + } + } + + private static class HeaderRenameQuickFix extends AbstractManifestQuickFix { private final String myNewName; - private HeaderNameSpellingQuickFix(Header header, HeaderNameMatch match) { - myHeader = header; - myNewName = match.getHeaderName(); + private HeaderRenameQuickFix(Header header, String newName) { + super(header); + myNewName = newName; } @NotNull @Override - public String getName() { - return ManifestBundle.message("inspection.header.fix", myNewName); + public String getText() { + return ManifestBundle.message("inspection.header.rename.fix", myNewName); + } + + @Override + public void invoke(@NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { + ((Header)startElement).setName(myNewName); + } + } + + private static class CustomHeaderQuickFix extends AbstractManifestQuickFix { + private final String myHeaderName; + private final Collection myHeaders; + + private CustomHeaderQuickFix(Header header, Collection headers) { + super(header); + myHeaderName = header.getName(); + myHeaders = headers; } @NotNull @Override - public String getFamilyName() { - return ManifestBundle.message("inspection.group"); + public String getText() { + return ManifestBundle.message("inspection.header.remember.fix", myHeaderName); } @Override - public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { - myHeader.setName(myNewName); + public void invoke(@NotNull Project project, @NotNull PsiFile file, @NotNull PsiElement startElement, @NotNull PsiElement endElement) { + myHeaders.add(myHeaderName); + + InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); + InspectionProfileManager.getInstance().fireProfileChanged(profile); } } } diff --git a/java/manifest/test/org/jetbrains/lang/manifest/ManifestPsiTest.java b/java/manifest/test/org/jetbrains/lang/manifest/ManifestPsiTest.java index 64d8fc27b1ed..7a82126508ee 100644 --- a/java/manifest/test/org/jetbrains/lang/manifest/ManifestPsiTest.java +++ b/java/manifest/test/org/jetbrains/lang/manifest/ManifestPsiTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ package org.jetbrains.lang.manifest; import com.intellij.psi.PsiFile; import com.intellij.testFramework.LightIdeaTestCase; import com.intellij.testFramework.LightPlatformTestCase; -import junit.framework.Assert; import org.jetbrains.annotations.Nullable; import org.jetbrains.lang.manifest.psi.Header; import org.jetbrains.lang.manifest.psi.HeaderValue; @@ -27,16 +26,16 @@ import org.jetbrains.lang.manifest.psi.ManifestFile; public class ManifestPsiTest extends LightIdeaTestCase { public void testFile() { ManifestFile file = createFile(""); - Assert.assertEquals(0, file.getSections().size()); - Assert.assertNull(file.getMainSection()); - Assert.assertEquals(0, file.getHeaders().size()); + assertEquals(0, file.getSections().size()); + assertNull(file.getMainSection()); + assertEquals(0, file.getHeaders().size()); file = createFile("Header: value\n\nAnother-Header: another value\n"); - Assert.assertEquals(2, file.getSections().size()); - Assert.assertNotNull(file.getMainSection()); - Assert.assertEquals(1, file.getHeaders().size()); - Assert.assertNotNull(file.getHeader("Header")); - Assert.assertNull(file.getHeader("Another-Header")); + assertEquals(2, file.getSections().size()); + assertNotNull(file.getMainSection()); + assertEquals(1, file.getHeaders().size()); + assertNotNull(file.getHeader("Header")); + assertNull(file.getHeader("Another-Header")); } public void testHeader() { @@ -54,15 +53,15 @@ public class ManifestPsiTest extends LightIdeaTestCase { private static void assertHeaderValue(ManifestFile file, String name, @Nullable String expected) { Header header = file.getHeader(name); - Assert.assertNotNull(header); + assertNotNull(header); HeaderValue value = header.getHeaderValue(); if (expected == null) { - Assert.assertNull(value); + assertNull(value); } else { - Assert.assertNotNull(value); - Assert.assertEquals(expected, value.getUnwrappedText()); + assertNotNull(value); + assertEquals(expected, value.getUnwrappedText()); } } } diff --git a/java/manifest/test/org/jetbrains/lang/manifest/MisspelledHeaderInspectionTest.java b/java/manifest/test/org/jetbrains/lang/manifest/MisspelledHeaderInspectionTest.java index c86149f15ca4..9ef828aefd61 100644 --- a/java/manifest/test/org/jetbrains/lang/manifest/MisspelledHeaderInspectionTest.java +++ b/java/manifest/test/org/jetbrains/lang/manifest/MisspelledHeaderInspectionTest.java @@ -19,25 +19,61 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import org.jetbrains.lang.manifest.highlighting.MisspelledHeaderInspection; +import java.util.Collections; import java.util.List; public class MisspelledHeaderInspectionTest extends LightCodeInsightFixtureTestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - myFixture.enableInspections(new MisspelledHeaderInspection()); + public void testNoProblem() { + doTest("Manifest-Version: 1.0", 0); } - public void testNoProblem() { - myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "Manifest-Version: 1.0\n"); - assertEquals(0, myFixture.getAvailableIntentions().size()); + public void testMixedCase() { + doTest("manifest-version: 1.0", 1); + } + + public void testMissedDash() { + doTest("ManifestVersion: 1.0", 1); + } + + public void testMisspelled() { + doTest("MainFestVersion: 1.0", 1); + } + + public void testTotallyIncorrect() { + doTest("some_totally_impossible_header: -", 0); } public void testFix() { + myFixture.enableInspections(new MisspelledHeaderInspection()); myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "ManifestVersion: 1.0\n"); List intentions = myFixture.filterAvailableIntentions("Change to"); - assertTrue(intentions.size() > 0); + assertEquals(1, intentions.size()); myFixture.launchAction(intentions.get(0)); myFixture.checkResult("Manifest-Version: 1.0\n"); } + + public void testCustomHeader() { + MisspelledHeaderInspection inspection = new MisspelledHeaderInspection(); + inspection.CUSTOM_HEADERS.add("Custom-Header"); + myFixture.enableInspections(inspection); + myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "Custom-Header: -\n"); + myFixture.checkHighlighting(); + } + + public void testCustomHeaderFix() { + MisspelledHeaderInspection inspection = new MisspelledHeaderInspection(); + myFixture.enableInspections(inspection); + myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, "Custom-Header: -\n"); + List intentions = myFixture.filterAvailableIntentions("Add "); + assertEquals(1, intentions.size()); + myFixture.launchAction(intentions.get(0)); + assertEquals(Collections.singleton("Custom-Header"), inspection.CUSTOM_HEADERS); + } + + private void doTest(String text, int expected) { + myFixture.enableInspections(new MisspelledHeaderInspection()); + myFixture.configureByText(ManifestFileTypeFactory.MANIFEST, text + "\n"); + myFixture.checkHighlighting(); + assertEquals(expected, myFixture.filterAvailableIntentions("Change to").size()); + } } From b4d925b0b08fa486cee354b2be9c3147f491ec63 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 14 Jun 2015 14:58:02 +0300 Subject: [PATCH 43/86] Don't throw IOException from dumpLogToStdout: wrap into RE in place To avoid extra wrapping in client test cases. --- .../testFramework/TestLoggerFactory.java | 21 ++++++++++++------- .../git4idea/GitCucumberWorld.java | 3 +-- .../tests/git4idea/test/GitPlatformTest.java | 12 +++-------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/TestLoggerFactory.java b/platform/testFramework/src/com/intellij/testFramework/TestLoggerFactory.java index 03771742ba3d..fa63dca8a260 100644 --- a/platform/testFramework/src/com/intellij/testFramework/TestLoggerFactory.java +++ b/platform/testFramework/src/com/intellij/testFramework/TestLoggerFactory.java @@ -95,16 +95,21 @@ public class TestLoggerFactory implements Logger.Factory { return PathManager.getSystemPath() + "/" + LOG_DIR; } - public static void dumpLogToStdout(@NotNull String testStartMarker) throws IOException { + public static void dumpLogToStdout(@NotNull String testStartMarker) { File ideaLog = new File(getTestLogDir(), "idea.log"); if (ideaLog.exists()) { - String logText = FileUtil.loadFile(ideaLog); - Pattern logStart = Pattern.compile("[0-9\\-, :\\[\\]]+(DEBUG|INFO|ERROR) - "); - System.out.println("\n\nIdea Log:"); - for (String line : StringUtil.splitByLines(logText.substring(Math.max(0, logText.lastIndexOf(testStartMarker))))) { - Matcher matcher = logStart.matcher(line); - int lineStart = matcher.lookingAt() ? matcher.end() : 0; - System.out.println(line.substring(lineStart)); + try { + String logText = FileUtil.loadFile(ideaLog); + Pattern logStart = Pattern.compile("[0-9\\-, :\\[\\]]+(DEBUG|INFO|ERROR) - "); + System.out.println("\n\nIdea Log:"); + for (String line : StringUtil.splitByLines(logText.substring(Math.max(0, logText.lastIndexOf(testStartMarker))))) { + Matcher matcher = logStart.matcher(line); + int lineStart = matcher.lookingAt() ? matcher.end() : 0; + System.out.println(line.substring(lineStart)); + } + } + catch (IOException e) { + throw new RuntimeException(e); } } } diff --git a/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java b/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java index 14c9ef89928d..e26aeb137997 100644 --- a/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java +++ b/plugins/git4idea/test-stepdefs/git4idea/GitCucumberWorld.java @@ -49,7 +49,6 @@ import org.jetbrains.annotations.NotNull; import org.junit.Assert; import java.io.File; -import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -206,7 +205,7 @@ public class GitCucumberWorld { } @After(order = 0) - public void dumpToLog(@NotNull Scenario result) throws IOException { + public void dumpToLog(@NotNull Scenario result) { if (result.isFailed()) { TestLoggerFactory.dumpLogToStdout(getStartTestMarker()); } diff --git a/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java b/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java index 68b3b17651f3..7136e148b21b 100644 --- a/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java +++ b/plugins/git4idea/tests/git4idea/test/GitPlatformTest.java @@ -43,7 +43,6 @@ import git4idea.repo.GitRepository; import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; -import java.io.IOException; import java.util.*; public abstract class GitPlatformTest extends UsefulTestCase { @@ -178,15 +177,10 @@ public abstract class GitPlatformTest extends UsefulTestCase { super.defaultRunBare(); } catch (Throwable throwable) { - try { - if (myTestStartedIndicator != null) { - TestLoggerFactory.dumpLogToStdout(myTestStartedIndicator); - } - throw throwable; - } - catch (IOException e) { - throw new RuntimeException(e); + if (myTestStartedIndicator != null) { + TestLoggerFactory.dumpLogToStdout(myTestStartedIndicator); } + throw throwable; } } From f96b2c8d06288d71950f080f48c951d1b1d68086 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 14 Jun 2015 15:06:48 +0300 Subject: [PATCH 44/86] [log test] dump debug log to stdout in case of test failure --- .../vcs/log/data/VcsLogRefresherTest.java | 9 ++++ .../vcs/log/impl/VcsLogPlatformTest.java | 52 +++++++++++++++++-- 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java index 240d07c3b4c4..a5f46fb9cca5 100644 --- a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java +++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java @@ -87,6 +87,15 @@ public class VcsLogRefresherTest extends VcsLogPlatformTest { } } + @NotNull + @Override + protected Collection getDebugLogCategories() { + return Arrays.asList("#" + SingleTaskController.class.getName(), + "#" + VcsLogRefresherImpl.class.getName(), + "#" + VcsLogRefresherTest.class.getName(), + "#" + TestVcsLogProvider.class.getName()); + } + public void test_initialize_shows_short_history() throws InterruptedException, ExecutionException, TimeoutException { DataPack result = myLoader.readFirstBlock(); assertNotNull(result); diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/VcsLogPlatformTest.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/VcsLogPlatformTest.java index 1f21aaf5b79f..89c7bbb410a6 100644 --- a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/VcsLogPlatformTest.java +++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/VcsLogPlatformTest.java @@ -15,21 +15,34 @@ */ package com.intellij.vcs.log.impl; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.TestLoggerFactory; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; +import java.util.Collection; +import java.util.Collections; + public abstract class VcsLogPlatformTest extends UsefulTestCase { - @NotNull protected Project myProject; - @NotNull protected VirtualFile myProjectRoot; - @NotNull protected String myProjectPath; + static { + Logger.setFactory(TestLoggerFactory.class); + } - @NotNull private IdeaProjectTestFixture myProjectFixture; + private static final Logger LOG = Logger.getInstance(VcsLogPlatformTest.class); + + protected Project myProject; + protected VirtualFile myProjectRoot; + protected String myProjectPath; + + private IdeaProjectTestFixture myProjectFixture; + private String myTestStartedIndicator; @SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors", "UnusedDeclaration"}) protected VcsLogPlatformTest() { @@ -39,6 +52,7 @@ public abstract class VcsLogPlatformTest extends UsefulTestCase { @Override protected void setUp() throws Exception { super.setUp(); + enableDebugLogging(); try { myProjectFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getTestName(true)).getFixture(); @@ -54,6 +68,22 @@ public abstract class VcsLogPlatformTest extends UsefulTestCase { myProjectPath = myProjectRoot.getPath(); } + private void enableDebugLogging() { + TestLoggerFactory.enableDebugLogging(myTestRootDisposable, ArrayUtil.toStringArray(getDebugLogCategories())); + myTestStartedIndicator = createTestStartedIndicator(); + LOG.info(myTestStartedIndicator); + } + + @NotNull + private String createTestStartedIndicator() { + return "Starting " + getClass().getName() + "." + getTestName(false) + Math.random(); + } + + @NotNull + protected Collection getDebugLogCategories() { + return Collections.emptyList(); + } + @Override public void tearDown() throws Exception { try { @@ -64,4 +94,16 @@ public abstract class VcsLogPlatformTest extends UsefulTestCase { } } -} + @Override + protected void defaultRunBare() throws Throwable { + try { + super.defaultRunBare(); + } + catch (Throwable throwable) { + if (myTestStartedIndicator != null) { + TestLoggerFactory.dumpLogToStdout(myTestStartedIndicator); + } + throw throwable; + } + } +} \ No newline at end of file From 1b4f4763395c29d95af496e3219719c4f07f3a53 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 14 Jun 2015 15:17:30 +0300 Subject: [PATCH 45/86] [log test] use AtomicInteger for the read first block counter The value returned to the test case might get out-of-date when int. Marking the field volatile seems to be enough, but let's make it AI to make the ++ operation synchronous if it will be needed in future. --- .../com/intellij/vcs/log/impl/TestVcsLogProvider.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java index 4728e2ea7ccd..c30d4c80fcbc 100644 --- a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java +++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java @@ -30,6 +30,7 @@ import java.awt.*; import java.util.*; import java.util.List; import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicInteger; import static org.junit.Assert.assertEquals; @@ -56,7 +57,7 @@ public class TestVcsLogProvider implements VcsLogProvider { @NotNull private final MockRefManager myRefManager; @NotNull private final ReducibleSemaphore myFullLogSemaphore; @NotNull private final ReducibleSemaphore myRefreshSemaphore; - private int myReadFirstBlockCounter; + @NotNull private AtomicInteger myReadFirstBlockCounter = new AtomicInteger(); private final Function myCommitToMetadataConvertor = new Function() { @@ -90,7 +91,7 @@ public class TestVcsLogProvider implements VcsLogProvider { throw new RuntimeException(e); } } - myReadFirstBlockCounter++; + myReadFirstBlockCounter.incrementAndGet(); assertRoot(root); List metadatas = ContainerUtil.map(myCommits.subList(0, requirements.getCommitCount()), myCommitToMetadataConvertor); @@ -197,11 +198,11 @@ public class TestVcsLogProvider implements VcsLogProvider { } public void resetReadFirstBlockCounter() { - myReadFirstBlockCounter = 0; + myReadFirstBlockCounter.set(0); } public int getReadFirstBlockCounter() { - return myReadFirstBlockCounter; + return myReadFirstBlockCounter.get(); } @Nullable From cbebf8b7157530b9a8d96e257ec17fb60b7c03ed Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sun, 14 Jun 2015 15:11:56 +0300 Subject: [PATCH 46/86] [log] add some debug logging to catch the test blinking --- .../src/com/intellij/vcs/log/data/DataPack.java | 4 ++++ .../vcs/log/data/SingleTaskController.java | 9 +++++++++ .../vcs/log/data/VcsLogRefresherImpl.java | 15 ++++++++++++++- .../vcs/log/data/VcsLogRefresherTest.java | 5 +++++ .../intellij/vcs/log/impl/TestVcsLogProvider.java | 13 +++++++++---- 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java index 859552d6e6c9..e213d7b735fb 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java @@ -116,4 +116,8 @@ public class DataPack { return myFull; } + @Override + public String toString() { + return "{DataPack. " + myPermanentGraph.getAllCommits().size() + " commits in " + myLogProviders.keySet().size() + " roots}"; + } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/SingleTaskController.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/SingleTaskController.java index 8d3e0d3fd9bf..0b9c0b540df0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/SingleTaskController.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/SingleTaskController.java @@ -15,6 +15,7 @@ */ package com.intellij.vcs.log.data; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -36,6 +37,8 @@ import java.util.List; */ public abstract class SingleTaskController { + private static final Logger LOG = Logger.getInstance(SingleTaskController.class); + @NotNull private final Consumer myResultHandler; @NotNull private final Object LOCK = new Object(); @@ -55,8 +58,10 @@ public abstract class SingleTaskController { public final void request(@NotNull Request requests) { synchronized (LOCK) { myAwaitingRequests.add(requests); + LOG.debug("Added requests: " + requests); if (!myActive) { startNewBackgroundTask(); + LOG.debug("Started a new bg task"); myActive = true; } } @@ -77,6 +82,7 @@ public abstract class SingleTaskController { synchronized (LOCK) { List requests = myAwaitingRequests; myAwaitingRequests = ContainerUtil.newArrayList(); + LOG.debug("Popped requests: " + requests); return requests; } } @@ -89,13 +95,16 @@ public abstract class SingleTaskController { protected final void taskCompleted(@Nullable Result result) { if (result != null) { myResultHandler.consume(result); + LOG.debug("Handled result: " + result); } synchronized (LOCK) { if (myAwaitingRequests.isEmpty()) { myActive = false; + LOG.debug("No more requests"); } else { startNewBackgroundTask(); + LOG.debug("Restarted a bg task"); } } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java index 65598d6914be..56f1d747b57d 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogRefresherImpl.java @@ -91,6 +91,7 @@ public class VcsLogRefresherImpl implements VcsLogRefresher { UIUtil.invokeLaterIfNeeded(new Runnable() { @Override public void run() { + LOG.debug("Starting a background task..."); ((ProgressManagerImpl)ProgressManager.getInstance()).runProcessWithProgressAsynchronously(refreshTask); } }); @@ -208,11 +209,13 @@ public class VcsLogRefresherImpl implements VcsLogRefresher { @Override public void run(@NotNull ProgressIndicator indicator) { + LOG.debug("Refresh task started"); indicator.setIndeterminate(true); DataPack dataPack = myCurrentDataPack; while (true) { List requests = mySingleTaskController.popRequests(); Collection rootsToRefresh = getRootsToRefresh(requests); + LOG.debug("Requests: " + requests + ". roots to refresh: " + rootsToRefresh); if (rootsToRefresh.isEmpty()) { mySingleTaskController.taskCompleted(dataPack); break; @@ -371,12 +374,22 @@ public class VcsLogRefresherImpl implements VcsLogRefresher { } private static class RefreshRequest { - private static final RefreshRequest RELOAD_ALL = new RefreshRequest(Collections.emptyList()); + private static final RefreshRequest RELOAD_ALL = new RefreshRequest(Collections.emptyList()) { + @Override + public String toString() { + return "RELOAD_ALL"; + } + }; private final Collection rootsToRefresh; RefreshRequest(@NotNull Collection rootsToRefresh) { this.rootsToRefresh = rootsToRefresh; } + + @Override + public String toString() { + return "{" + rootsToRefresh + "}"; + } } private static abstract class ProviderIterator { diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java index a5f46fb9cca5..acf26d51c312 100644 --- a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java +++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogRefresherTest.java @@ -16,6 +16,7 @@ package com.intellij.vcs.log.data; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.progress.impl.ProgressManagerImpl; @@ -38,6 +39,8 @@ import static com.intellij.vcs.log.TimedCommitParser.log; public class VcsLogRefresherTest extends VcsLogPlatformTest { + private static final Logger LOG = Logger.getInstance(VcsLogRefresherTest.class); + private static final int RECENT_COMMITS_COUNT = 2; public static final Consumer FAILING_EXCEPTION_HANDLER = new Consumer() { @Override @@ -209,7 +212,9 @@ public class VcsLogRefresherTest extends VcsLogPlatformTest { UIUtil.invokeLaterIfNeeded(new Runnable() { @Override public void run() { + LOG.debug("Starting a background task..."); myStartedTasks.add(((ProgressManagerImpl)ProgressManager.getInstance()).runProcessWithProgressAsynchronously(refreshTask)); + LOG.debug(myStartedTasks.size() + " started tasks"); } }); } diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java index c30d4c80fcbc..c4e76891a06f 100644 --- a/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java +++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/impl/TestVcsLogProvider.java @@ -15,6 +15,7 @@ */ package com.intellij.vcs.log.impl; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.VcsKey; import com.intellij.openapi.vcs.changes.committed.MockAbstractVcs; @@ -36,6 +37,8 @@ import static org.junit.Assert.assertEquals; public class TestVcsLogProvider implements VcsLogProvider { + private static final Logger LOG = Logger.getInstance(TestVcsLogProvider.class); + public static final VcsRefType BRANCH_TYPE = new VcsRefType() { @Override public boolean isBranch() { @@ -80,9 +83,8 @@ public class TestVcsLogProvider implements VcsLogProvider { @NotNull @Override - public DetailedLogData readFirstBlock(@NotNull final VirtualFile root, - @NotNull Requirements requirements) - throws VcsException { + public DetailedLogData readFirstBlock(@NotNull final VirtualFile root, @NotNull Requirements requirements) throws VcsException { + LOG.debug("readFirstBlock began"); if (requirements instanceof VcsLogProviderRequirementsEx && ((VcsLogProviderRequirementsEx)requirements).isRefresh()) { try { myRefreshSemaphore.acquire(); @@ -91,7 +93,8 @@ public class TestVcsLogProvider implements VcsLogProvider { throw new RuntimeException(e); } } - myReadFirstBlockCounter.incrementAndGet(); + int readFirstBlockCounter = myReadFirstBlockCounter.incrementAndGet(); + LOG.debug("readFirstBlock passed the semaphore: " + readFirstBlockCounter); assertRoot(root); List metadatas = ContainerUtil.map(myCommits.subList(0, requirements.getCommitCount()), myCommitToMetadataConvertor); @@ -101,12 +104,14 @@ public class TestVcsLogProvider implements VcsLogProvider { @NotNull @Override public LogData readAllHashes(@NotNull VirtualFile root, @NotNull Consumer commitConsumer) throws VcsException { + LOG.debug("readAllHashes"); try { myFullLogSemaphore.acquire(); } catch (InterruptedException e) { throw new RuntimeException(e); } + LOG.debug("readAllHashes passed the semaphore"); assertRoot(root); for (TimedVcsCommit commit : myCommits) { commitConsumer.consume(commit); From 3dfa1f665e5bf764dca188de85f0610910fb9a2d Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sun, 14 Jun 2015 14:29:03 +0200 Subject: [PATCH 47/86] acceletatorSelectionForeground should be white --- .../src/com/intellij/ide/ui/laf/intellijlaf_mac.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties index a193b504a3f4..ab711d9ae3e6 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties @@ -1,3 +1,4 @@ +# suppress inspection "UnusedProperty" for whole file intellijlaf.background=ececec window=ececec @@ -9,6 +10,7 @@ Spinner.background=ececec Spinner.darcula.disabledButtonColor=ececec ComboBoxUI=com.intellij.ide.ui.laf.intellij.MacIntelliJComboBoxUI +MenuItem.acceleratorSelectionForeground=ffffff SplitPane.highlight=ececec From 9e3afbc15a64637946c5cbec5430cafff74f7471 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sun, 14 Jun 2015 14:30:17 +0200 Subject: [PATCH 48/86] new mac laf: patch all fonts to system font face, but munues to Lucida Grande --- .../com/intellij/ide/ui/laf/IntelliJLaf.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java index 363e46d03ffa..ab038a3f386a 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/IntelliJLaf.java @@ -22,6 +22,7 @@ import javax.swing.*; import javax.swing.plaf.FontUIResource; import javax.swing.plaf.metal.DefaultMetalTheme; import java.awt.*; +import java.util.HashSet; /** * @author Konstantin Bulenkov @@ -52,11 +53,23 @@ public class IntelliJLaf extends DarculaLaf { } private static void installMacOSXFonts(UIDefaults defaults) { - FontUIResource font = new FontUIResource("HelveticaNeue-CondensedBlack", Font.PLAIN, 13); - defaults.put("Label.font", font); - defaults.put("CheckBox.font", font); - defaults.put("RadioButton.font", font); - defaults.put("ComboBox.font", font); + String face = "HelveticaNeue-CondensedBlack"; + LafManagerImpl.initFontDefaults(defaults, face, 13); + for (Object key : new HashSet(defaults.keySet())) { + Object value = defaults.get(key); + if (value instanceof FontUIResource) { + FontUIResource font = (FontUIResource)value; + if (font.getFamily().equals("Lucida Grande") || font.getFamily().equals("Serif")) { + if (!key.toString().contains("Menu")) { + defaults.put(key, new FontUIResource(face, font.getStyle(), font.getSize())); + } + } + } + } + Font menuFont = new Font("Lucida Grande", Font.PLAIN, 14); + defaults.put("Menu.font", menuFont); + defaults.put("MenuItem.font", menuFont); + defaults.put("MenuItem.acceleratorFont", menuFont); } public static boolean isGraphite() { From f8e73a22e6c2134f456ce583e44df09556f3326d Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sun, 14 Jun 2015 14:38:23 +0200 Subject: [PATCH 49/86] system colors for popup menu and other menues --- .../src/com/intellij/ide/ui/laf/intellijlaf_mac.properties | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties index ab711d9ae3e6..751c0875964f 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties @@ -11,6 +11,9 @@ Spinner.darcula.disabledButtonColor=ececec ComboBoxUI=com.intellij.ide.ui.laf.intellij.MacIntelliJComboBoxUI MenuItem.acceleratorSelectionForeground=ffffff +PopupMenu.background=f6f6f6 +MenuItem.background=f6f6f6 +Menu.background=f6f6f6 SplitPane.highlight=ececec From 149179a4e88ffedef046ef9d549fb31e047715de Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sun, 14 Jun 2015 14:43:12 +0200 Subject: [PATCH 50/86] setup inactive backgrounds for all components --- .../src/com/intellij/ide/ui/laf/intellijlaf_mac.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties index 751c0875964f..07d3d6747b99 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_mac.properties @@ -1,5 +1,7 @@ # suppress inspection "UnusedProperty" for whole file intellijlaf.background=ececec +intellijlaf.selectionBackgroundInactive=dcdcdc +intellijlaf.selectionInactiveBackground=dcdcdc window=ececec CheckBoxUI=com.intellij.ide.ui.laf.intellij.MacIntelliJCheckBoxUI From d2aeaeb2d4c32ca47981dcf85968e82cce0b1fa4 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 12 Jun 2015 11:19:32 +0200 Subject: [PATCH 51/86] cleanup --- .../util/ui/tree/AbstractFileTreeTable.java | 39 +++++++------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java b/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java index 416d584441b0..17d5951b93ad 100644 --- a/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java +++ b/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java @@ -60,6 +60,7 @@ public abstract class AbstractFileTreeTable extends TreeTable { super(new MyModel(project, valueClass, valueTitle, filter)); myProject = project; + //noinspection unchecked myModel = (MyModel)getTableModel(); myModel.setTreeTable(this); @@ -96,21 +97,13 @@ public abstract class AbstractFileTreeTable extends TreeTable { } FileNode fileNode = (FileNode)value; VirtualFile file = fileNode.getObject(); - if (fileNode.getParent() instanceof FileNode) { - setText(file.getName()); - } - else { - setText(file.getPresentableUrl()); - } - - Icon icon = file.isDirectory() ? PlatformIcons.DIRECTORY_CLOSED_ICON : IconUtil.getIcon(file, 0, null); - setIcon(icon); + setText(fileNode.getParent() instanceof FileNode ? file.getName() : file.getPresentableUrl()); + setIcon(file.isDirectory() ? PlatformIcons.DIRECTORY_CLOSED_ICON : IconUtil.getIcon(file, 0, null)); return this; } }); getTableHeader().setReorderingAllowed(false); - setSelectionMode(ListSelectionModel.SINGLE_SELECTION); setPreferredScrollableViewportSize(new Dimension(300, getRowHeight() * 10)); @@ -140,8 +133,7 @@ public abstract class AbstractFileTreeTable extends TreeTable { public static void press(final Container comboComponent) { if (comboComponent instanceof JButton) { - final JButton button = (JButton)comboComponent; - button.doClick(); + ((JButton)comboComponent).doClick(); } else { for (int i = 0; i < comboComponent.getComponentCount(); i++) { @@ -191,8 +183,7 @@ public abstract class AbstractFileTreeTable extends TreeTable { public void reset(@NotNull Map mappings) { myModel.reset(mappings); - final TreeNode root = (TreeNode)myModel.getRoot(); - myModel.nodeChanged(root); + myModel.nodeChanged((TreeNode)myModel.getRoot()); getTree().setModel(null); getTree().setModel(myModel); TreeUtil.expandRootChildIfOnlyOne(getTree()); @@ -223,7 +214,6 @@ public abstract class AbstractFileTreeTable extends TreeTable { } } - private static class MyModel extends DefaultTreeModel implements TreeTableModel { private final Map myCurrentMapping = new HashMap(); private final Class myValueClass; @@ -310,11 +300,14 @@ public abstract class AbstractFileTreeTable extends TreeTable { @Override public void setValueAt(final Object aValue, final Object node, final int column) { - final DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node; - final Object userObject = treeNode.getUserObject(); - if (userObject instanceof Project) return; + final Object userObject = ((DefaultMutableTreeNode)node).getUserObject(); + if (userObject instanceof Project) { + return; + } + final VirtualFile file = (VirtualFile)userObject; - final T t = (T)aValue; + @SuppressWarnings("unchecked") + T t = (T)aValue; if (t == null || myTreeTable.isNullObject(t)) { myCurrentMapping.remove(file); } @@ -426,8 +419,8 @@ public abstract class AbstractFileTreeTable extends TreeTable { public void clearCachedChildren() { if (children != null) { for (Object child : children) { - ConvenientNode node = (ConvenientNode)child; - node.clearCachedChildren(); + //noinspection unchecked + ((ConvenientNode)child).clearCachedChildren(); } } removeAllChildren(); @@ -451,14 +444,12 @@ public abstract class AbstractFileTreeTable extends TreeTable { @Override protected void appendChildrenTo(@NotNull final Collection children) { - VirtualFile[] childrenf = getObject().getChildren(); ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); - for (VirtualFile child : childrenf) { + for (VirtualFile child : getObject().getChildren()) { if (myFilter.accept(child) && fileIndex.isInContent(child)) { children.add(new FileNode(child, myProject, myFilter)); } } } } - } From 95df71eac54ccb0a4c50adbfd226d2867facbb9b Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Fri, 12 Jun 2015 13:02:34 +0200 Subject: [PATCH 52/86] show excluded file in file tree (remote urls) --- .../util/ui/tree/AbstractFileTreeTable.java | 24 ++++++++-- .../util/ui/tree/NonContentFileFilter.java | 47 +++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/util/ui/tree/NonContentFileFilter.java diff --git a/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java b/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java index 17d5951b93ad..5287db9087ce 100644 --- a/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java +++ b/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java @@ -48,7 +48,7 @@ import java.awt.*; import java.util.*; import java.util.List; -public abstract class AbstractFileTreeTable extends TreeTable { +public class AbstractFileTreeTable extends TreeTable { private final MyModel myModel; private final Project myProject; @@ -57,7 +57,16 @@ public abstract class AbstractFileTreeTable extends TreeTable { @NotNull String valueTitle, @NotNull VirtualFileFilter filter, boolean showProjectNode) { - super(new MyModel(project, valueClass, valueTitle, filter)); + this(project, valueClass, valueTitle, filter, showProjectNode, true); + } + + public AbstractFileTreeTable(@NotNull Project project, + @NotNull Class valueClass, + @NotNull String valueTitle, + @NotNull VirtualFileFilter filter, + boolean showProjectNode, + boolean filterNonContentFiles) { + super(new MyModel(project, valueClass, valueTitle, filterNonContentFiles ? new NonContentFileFilter(project, filter) : filter)); myProject = project; //noinspection unchecked @@ -85,6 +94,7 @@ public abstract class AbstractFileTreeTable extends TreeTable { getTree().setShowsRootHandles(true); getTree().setLineStyleAngled(); getTree().setRootVisible(showProjectNode); + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); getTree().setCellRenderer(new DefaultTreeCellRenderer() { @Override public Component getTreeCellRendererComponent(final JTree tree, final Object value, final boolean sel, final boolean expanded, @@ -98,7 +108,12 @@ public abstract class AbstractFileTreeTable extends TreeTable { FileNode fileNode = (FileNode)value; VirtualFile file = fileNode.getObject(); setText(fileNode.getParent() instanceof FileNode ? file.getName() : file.getPresentableUrl()); - setIcon(file.isDirectory() ? PlatformIcons.DIRECTORY_CLOSED_ICON : IconUtil.getIcon(file, 0, null)); + if (file.isDirectory()) { + setIcon(fileIndex.isExcluded(file) ? AllIcons.Modules.ExcludeRoot : PlatformIcons.DIRECTORY_CLOSED_ICON); + } + else { + setIcon(IconUtil.getIcon(file, 0, null)); + } return this; } }); @@ -444,9 +459,8 @@ public abstract class AbstractFileTreeTable extends TreeTable { @Override protected void appendChildrenTo(@NotNull final Collection children) { - ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); for (VirtualFile child : getObject().getChildren()) { - if (myFilter.accept(child) && fileIndex.isInContent(child)) { + if (myFilter.accept(child)) { children.add(new FileNode(child, myProject, myFilter)); } } diff --git a/platform/lang-impl/src/com/intellij/util/ui/tree/NonContentFileFilter.java b/platform/lang-impl/src/com/intellij/util/ui/tree/NonContentFileFilter.java new file mode 100644 index 000000000000..3eeef5869217 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/util/ui/tree/NonContentFileFilter.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util.ui.tree; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileFilter; +import org.jetbrains.annotations.NotNull; + +public class NonContentFileFilter implements VirtualFileFilter { + private final Project project; + private final VirtualFileFilter filter; + + private ProjectFileIndex fileIndex; + + public NonContentFileFilter(@NotNull Project project, @NotNull VirtualFileFilter filter) { + this.project = project; + this.filter = filter; + } + + @Override + public boolean accept(@NotNull VirtualFile file) { + if (!filter.accept(file)) { + return false; + } + + if (fileIndex == null) { + fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); + } + return fileIndex.isInContent(file); + } +} From 163c76b9bd60a96b1cfdf56f83b2a50eb75dee3e Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sun, 14 Jun 2015 19:39:35 +0200 Subject: [PATCH 53/86] init WEB-16829 "too soon" typescript breakpoints are not hit --- .../src/com/intellij/util/UrlImpl.java | 4 +-- .../jetbrains/io/ChannelBufferToString.java | 17 ++----------- .../src/org/jetbrains/io/JsonReaderEx.java | 18 +++++++++++++ .../src/org/jetbrains/io/MessageDecoder.java | 2 +- .../jetbrains/debugger/DebugEventAdapter.java | 2 +- .../debugger/DebugEventListener.java | 2 +- .../org/jetbrains/debugger/ScriptManager.java | 4 +++ .../debugger/ScriptManagerBaseEx.java | 7 +++++- .../debugger/sourcemap/SourceMapDecoder.java | 17 +++---------- .../debugger/sourcemap/SourceResolver.java | 25 +++++++++++++------ 10 files changed, 56 insertions(+), 42 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/util/UrlImpl.java b/platform/platform-impl/src/com/intellij/util/UrlImpl.java index 023865164405..6876998e0a03 100644 --- a/platform/platform-impl/src/com/intellij/util/UrlImpl.java +++ b/platform/platform-impl/src/com/intellij/util/UrlImpl.java @@ -44,7 +44,7 @@ public final class UrlImpl implements Url { public UrlImpl(@Nullable String scheme, @Nullable String authority, @Nullable String path, @Nullable String parameters) { this.scheme = scheme; this.authority = authority; - this.path = StringUtil.isEmpty(path) && !StringUtil.isEmpty(authority) ? "/" : StringUtil.notNullize(path); + this.path = StringUtil.notNullize(path); this.parameters = StringUtil.nullize(parameters); } @@ -112,7 +112,7 @@ public final class UrlImpl implements Url { // relative path - special url, encoding is not required // authority is null in case of URI - if ((path.charAt(0) != '/' || authority == null) && !isInLocalFileSystem()) { + if ((authority == null || (!path.isEmpty() && path.charAt(0) != '/')) && !isInLocalFileSystem()) { return toDecodedForm(); } diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelBufferToString.java b/platform/platform-impl/src/org/jetbrains/io/ChannelBufferToString.java index df61a92f987e..9bf08d705a4e 100644 --- a/platform/platform-impl/src/org/jetbrains/io/ChannelBufferToString.java +++ b/platform/platform-impl/src/org/jetbrains/io/ChannelBufferToString.java @@ -1,6 +1,5 @@ package org.jetbrains.io; -import com.intellij.util.text.CharArrayCharSequence; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtilEx; @@ -13,13 +12,13 @@ import java.nio.CharBuffer; public final class ChannelBufferToString { @NotNull public static CharSequence readChars(@NotNull ByteBuf buffer) throws IOException { - return new MyCharArrayCharSequence(readIntoCharBuffer(buffer, buffer.readableBytes(), null)); + return new JsonReaderEx.CharSequenceBackedByChars(readIntoCharBuffer(buffer, buffer.readableBytes(), null)); } @SuppressWarnings("unused") @NotNull public static CharSequence readChars(@NotNull ByteBuf buffer, int byteCount) throws IOException { - return new MyCharArrayCharSequence(readIntoCharBuffer(buffer, byteCount, null)); + return new JsonReaderEx.CharSequenceBackedByChars(readIntoCharBuffer(buffer, byteCount, null)); } @NotNull @@ -34,16 +33,4 @@ public final class ChannelBufferToString { public static void writeIntAsAscii(int value, @NotNull ByteBuf buffer) { ByteBufUtil.writeAscii(buffer, new StringBuilder().append(value)); } - - // we must return string on subSequence() - JsonReaderEx will call toString in any case - public static final class MyCharArrayCharSequence extends CharArrayCharSequence { - public MyCharArrayCharSequence(@NotNull CharBuffer charBuffer) { - super(charBuffer.array(), charBuffer.arrayOffset(), charBuffer.position()); - } - - @Override - public CharSequence subSequence(int start, int end) { - return start == 0 && end == length() ? this : new String(myChars, myStart + start, end - start); - } - } } \ No newline at end of file diff --git a/platform/platform-impl/src/org/jetbrains/io/JsonReaderEx.java b/platform/platform-impl/src/org/jetbrains/io/JsonReaderEx.java index 37cf6bf7066c..aa783b158764 100644 --- a/platform/platform-impl/src/org/jetbrains/io/JsonReaderEx.java +++ b/platform/platform-impl/src/org/jetbrains/io/JsonReaderEx.java @@ -17,10 +17,12 @@ package org.jetbrains.io; import com.google.gson.JsonParseException; import com.google.gson.stream.JsonToken; +import com.intellij.util.text.CharArrayCharSequence; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.Closeable; +import java.nio.CharBuffer; import java.util.Arrays; public final class JsonReaderEx implements Closeable { @@ -116,6 +118,22 @@ public final class JsonReaderEx implements Closeable { this.stack = stack; } + // we must return string on subSequence() - JsonReaderEx will call toString in any case + public static final class CharSequenceBackedByChars extends CharArrayCharSequence { + public CharSequenceBackedByChars(@NotNull CharBuffer charBuffer) { + super(charBuffer.array(), charBuffer.arrayOffset(), charBuffer.position()); + } + + public CharSequenceBackedByChars(@NotNull char[] chars, int start, int end) { + super(chars, start, end); + } + + @Override + public CharSequence subSequence(int start, int end) { + return start == 0 && end == length() ? this : new String(myChars, myStart + start, end - start); + } + } + private final static class JsonScope { /** * An array with no elements requires no separators or newlines before diff --git a/platform/platform-impl/src/org/jetbrains/io/MessageDecoder.java b/platform/platform-impl/src/org/jetbrains/io/MessageDecoder.java index 6746a4c1d2f1..3f672c3916d6 100644 --- a/platform/platform-impl/src/org/jetbrains/io/MessageDecoder.java +++ b/platform/platform-impl/src/org/jetbrains/io/MessageDecoder.java @@ -44,7 +44,7 @@ public abstract class MessageDecoder extends Decoder { chunkedContent = null; consumedContentByteCount = 0; } - return new ChannelBufferToString.MyCharArrayCharSequence(ChannelBufferToString.readIntoCharBuffer(input, required, charBuffer)); + return new JsonReaderEx.CharSequenceBackedByChars(ChannelBufferToString.readIntoCharBuffer(input, required, charBuffer)); } } diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java index 3ee0bb525532..0724cfe6c989 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventAdapter.java @@ -18,7 +18,7 @@ public abstract class DebugEventAdapter implements DebugEventListener { } @Override - public void scriptAdded(@NotNull Script script, @Nullable String sourceMapData) { + public void scriptAdded(@NotNull Script script, @Nullable CharSequence sourceMapData) { } @Override diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java index 7a523229adc7..d3f6ac2a649f 100755 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/DebugEventListener.java @@ -29,7 +29,7 @@ public interface DebugEventListener extends EventListener { /** * Reports that a new script has been loaded. */ - void scriptAdded(@NotNull Script script, @Nullable String sourceMapData); + void scriptAdded(@NotNull Script script, @Nullable CharSequence sourceMapData); void sourceMapFound(@NotNull Script script, @Nullable Url sourceMapUrl, @NotNull String sourceMapData); diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManager.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManager.java index 1132b284e16d..4b3a20e0f6ec 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManager.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManager.java @@ -2,6 +2,7 @@ package org.jetbrains.debugger; import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; +import com.intellij.util.Url; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.concurrency.Promise; @@ -37,6 +38,9 @@ public interface ScriptManager { @Nullable Script findScriptByUrl(@NotNull String rawUrl); + @Nullable + Script findScriptByUrl(@NotNull Url url); + @Nullable Script findScriptById(@NotNull String id); diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManagerBaseEx.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManagerBaseEx.java index 05cca7fd4317..b8286f77b15c 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManagerBaseEx.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/ScriptManagerBaseEx.java @@ -35,7 +35,12 @@ public abstract class ScriptManagerBaseEx