From 1f8341c8828f981eef8718b4d8fd09527d29f9fe Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 25 Oct 2017 16:40:30 +0700 Subject: [PATCH 01/46] DataFlowInspection: specific message for ioobe contracts, messages moved to resources Fixes IDEA-180501 Confusing warning about list get method --- .../dataFlow/ContractValue.java | 20 +++++++++++++++++++ .../dataFlow/DataFlowInspectionBase.java | 19 +++++++++++++----- .../dataFlow/fixture/ArrayLength.java | 2 +- .../dataFlow/fixture/CustomContracts.java | 2 +- .../fixture/ForEachOverEmptyCollection.java | 2 +- .../fixture/LongRangeKnownMethods.java | 4 ++-- .../src/messages/InspectionsBundle.properties | 2 ++ 7 files changed, 41 insertions(+), 10 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractValue.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractValue.java index 813358b8f9de..cabde8c540fc 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractValue.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ContractValue.java @@ -33,6 +33,13 @@ public abstract class ContractValue { abstract DfaValue makeDfaValue(DfaValueFactory factory, DfaCallArguments arguments); + /** + * @return true if this contract value represents a bounds-checking condition + */ + boolean isBoundCheckingCondition() { + return false; + } + public static ContractValue qualifier() { return Qualifier.INSTANCE; } @@ -160,6 +167,19 @@ public abstract class ContractValue { myRelationType = type; } + @Override + boolean isBoundCheckingCondition() { + switch (myRelationType) { + case LE: + case LT: + case GE: + case GT: + return true; + default: + return false; + } + } + @Override DfaValue makeDfaValue(DfaValueFactory factory, DfaCallArguments arguments) { return factory.createCondition(myLeft.makeDfaValue(factory, arguments), myRelationType, myRight.makeDfaValue(factory, arguments)); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index 99ad6247c391..2fe5b75c41c5 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -393,13 +393,21 @@ public class DataFlowInspectionBase extends AbstractBaseJavaLocalInspectionTool private static void reportAlwaysFailingCalls(ProblemsHolder holder, DataFlowInstructionVisitor visitor, HashSet reportedAnchors) { - for (PsiCall call : visitor.getAlwaysFailingCalls()) { - if (TestUtils.isExceptionExpected(call)) continue; + visitor.getAlwaysFailingCalls().forEach((call, contracts) -> { + if (TestUtils.isExceptionExpected(call)) return; PsiMethod method = call.resolveMethod(); if (method != null && reportedAnchors.add(call)) { - holder.registerProblem(getElementToHighlight(call), "The call to '#ref' always fails, according to its method contracts"); + holder.registerProblem(getElementToHighlight(call), getContractMessage(contracts)); } + }); + } + + @NotNull + private static String getContractMessage(List contracts) { + if (contracts.stream().allMatch(mc -> mc.getConditions().stream().allMatch(cv -> cv.isBoundCheckingCondition()))) { + return InspectionsBundle.message("dataflow.message.contract.fail.index"); } + return InspectionsBundle.message("dataflow.message.contract.fail"); } @NotNull private static PsiElement getElementToHighlight(@NotNull PsiCall call) { @@ -965,8 +973,9 @@ public class DataFlowInspectionBase extends AbstractBaseJavaLocalInspectionTool return myOptionalQualifiers; } - Collection getAlwaysFailingCalls() { - return StreamEx.ofKeys(myFailingCalls, v -> v).map(MethodCallInstruction::getCallExpression).toList(); + Map> getAlwaysFailingCalls() { + return StreamEx.ofKeys(myFailingCalls, v -> v) + .mapToEntry(MethodCallInstruction::getCallExpression, MethodCallInstruction::getContracts).toMap(); } boolean isAlwaysReturnsNotNull(Instruction[] instructions) { diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ArrayLength.java b/java/java-tests/testData/inspection/dataFlow/fixture/ArrayLength.java index 6a4f3ce92f8a..2250766f8d45 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/ArrayLength.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ArrayLength.java @@ -26,6 +26,6 @@ public final class ArrayLength { System.out.println("Impossible"); } Arrays.fill(x, -1); - Arrays.fill(x, -1, -1, -1); + Arrays.fill(x, -1, -1, -1); } } \ No newline at end of file diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/CustomContracts.java b/java/java-tests/testData/inspection/dataFlow/fixture/CustomContracts.java index 942a7c3173bd..23a68ff1ed3c 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/CustomContracts.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/CustomContracts.java @@ -1,6 +1,6 @@ public class CustomContracts { public void testSubstring(String s) { - if (s.substring(-1).length() == 0) { + if (s.substring(-1).length() == 0) { System.out.println("Oops"); } } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ForEachOverEmptyCollection.java b/java/java-tests/testData/inspection/dataFlow/fixture/ForEachOverEmptyCollection.java index d346355acab7..0990c3fa1f60 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/ForEachOverEmptyCollection.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ForEachOverEmptyCollection.java @@ -46,7 +46,7 @@ public class ForEachOverEmptyCollection { } if(!hasItem) { System.out.println( - list.get(max == null ? 0 : 1)); + list.get(max == null ? 0 : 1)); } } } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/LongRangeKnownMethods.java b/java/java-tests/testData/inspection/dataFlow/fixture/LongRangeKnownMethods.java index 54d1a5634956..278935eaefc0 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/LongRangeKnownMethods.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/LongRangeKnownMethods.java @@ -196,13 +196,13 @@ public class LongRangeKnownMethods { void testEmptyListGet(List list) { if (list.isEmpty()) { - System.out.println(list.get(0)); + System.out.println(list.get(0)); } } void testBoundError(List list) { if (list.size() < 10) { - System.out.println(list.get(10)); + System.out.println(list.get(10)); } } diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index 3d10baed8a29..44f93fa276f3 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -64,6 +64,8 @@ dataflow.message.npe.field.access=Dereference of #ref #loc may prod dataflow.message.cce=Casting {0} to #ref #loc may produce java.lang.ClassCastException dataflow.message.arraystore=Storing element of type {0} to array of {1} elements may produce java.lang.ArrayStoreException dataflow.message.redundant.instanceof=Condition #ref #loc is redundant and can be replaced with != null +dataflow.message.contract.fail=The call to '#ref' always fails, according to its method contracts +dataflow.message.contract.fail.index=The call to '#ref' always fails as index is out of bounds dataflow.message.constant.condition=Condition #ref #loc is always {0} dataflow.message.constant.condition.when.reached=Condition #ref #loc is always {0} when reached dataflow.message.loop.on.empty.array=Array #ref is always empty From 20d76b15800f832c923b045474eadb8c719b1914 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 25 Oct 2017 12:15:31 +0200 Subject: [PATCH 02/46] IDEA-181135 Go to File: with "Include non-project files" = No out-of-project files are still suggested --- .../com/intellij/java/navigation/ChooseByNameTest.groovy | 5 +++++ .../src/com/intellij/ide/actions/DirectoryPathMatcher.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/java/java-tests/testSrc/com/intellij/java/navigation/ChooseByNameTest.groovy b/java/java-tests/testSrc/com/intellij/java/navigation/ChooseByNameTest.groovy index cc98715d284e..426a0abc1445 100644 --- a/java/java-tests/testSrc/com/intellij/java/navigation/ChooseByNameTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/navigation/ChooseByNameTest.groovy @@ -419,6 +419,11 @@ class Intf { assert gotoFile('langcsequence', false) == [charSeq.containingFile, seq] } + void "test show no matches from jdk when there are in project"() { + def file = addEmptyFile("String.txt") + assert gotoFile('Str', false) == [file] + } + void "test fix keyboard layout"() { assert (gotoClass('Ыекштп')[0] as PsiClass).name == 'String' assert (gotoSymbol('Ыекштп')[0] as PsiClass).name == 'String' diff --git a/platform/lang-impl/src/com/intellij/ide/actions/DirectoryPathMatcher.java b/platform/lang-impl/src/com/intellij/ide/actions/DirectoryPathMatcher.java index 6a01b2b565d4..72fe2de80751 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/DirectoryPathMatcher.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/DirectoryPathMatcher.java @@ -98,7 +98,7 @@ class DirectoryPathMatcher { if (myFiles == null) return fileSearchScope; VirtualFile[] array = ContainerUtil.map2Array(myFiles, VirtualFile.class, p -> p.first); - return fileSearchScope.intersectWith(GlobalSearchScopesCore.directoriesScope(myModel.getProject(), true, array)); + return GlobalSearchScopesCore.directoriesScope(myModel.getProject(), true, array).intersectWith(fileSearchScope); } From 4c754d31eb72f4f474db6d9d65fda3f0d062cd3e Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 25 Oct 2017 12:18:01 +0200 Subject: [PATCH 03/46] directory scopes shouldn't assume they're always inside project (IDEA-181135) --- .../intellij/psi/search/GlobalSearchScopesCore.java | 4 ++-- .../intellij/psi/search/GlobalSearchScopeTest.java | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java b/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java index 9877e03ccd82..616c73a9390b 100644 --- a/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java +++ b/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java @@ -248,7 +248,7 @@ public class GlobalSearchScopesCore { @Override public boolean isSearchInLibraries() { - return false; + return true; } @Override @@ -346,7 +346,7 @@ public class GlobalSearchScopesCore { @Override public boolean isSearchInLibraries() { - return false; + return true; } @Override diff --git a/platform/platform-tests/testSrc/com/intellij/psi/search/GlobalSearchScopeTest.java b/platform/platform-tests/testSrc/com/intellij/psi/search/GlobalSearchScopeTest.java index 89d9e9bf9bbe..5bc8c3699e3f 100644 --- a/platform/platform-tests/testSrc/com/intellij/psi/search/GlobalSearchScopeTest.java +++ b/platform/platform-tests/testSrc/com/intellij/psi/search/GlobalSearchScopeTest.java @@ -18,6 +18,7 @@ package com.intellij.psi.search; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.PsiTestUtil; import com.intellij.testFramework.TempFiles; import org.jetbrains.annotations.NotNull; @@ -107,4 +108,16 @@ public class GlobalSearchScopeTest extends PlatformTestCase { assertFalse(GlobalSearchScope.fileScope(myProject, file1).intersectWith(trueIntersection).contains(file2)); assertEquals(1, targetCalled.get()); } + + public void testDirScopeSearchInLibraries() throws IOException { + VirtualFile libRoot = getVirtualFile(createTempDir("libRoot")); + VirtualFile contentRoot = getVirtualFile(createTempDir("contentRoot")); + + PsiTestUtil.removeAllRoots(getModule(), null); + PsiTestUtil.addContentRoot(getModule(), contentRoot); + PsiTestUtil.addLibrary(getModule(), libRoot.getPath()); + + assertTrue(GlobalSearchScopes.directoryScope(myProject, libRoot, true).isSearchInLibraries()); + assertTrue(GlobalSearchScopes.directoriesScope(myProject, true, libRoot, contentRoot).isSearchInLibraries()); + } } \ No newline at end of file From 5fe541d796fc60a843a19234e94528095264f594 Mon Sep 17 00:00:00 2001 From: Konstantin Aleev Date: Fri, 20 Oct 2017 15:00:09 +0300 Subject: [PATCH 04/46] IDEA-180884 RunDashboard: keep focus on the tree when selecting started configuration --- .../execution/dashboard/RunDashboardContent.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardContent.java b/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardContent.java index 6c77e1ae3248..953a9b882e4b 100644 --- a/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardContent.java +++ b/platform/lang-impl/src/com/intellij/execution/dashboard/RunDashboardContent.java @@ -305,9 +305,15 @@ public class RunDashboardContent extends JPanel implements TreeContent, Disposab updateContentToolbar(content); if (content != null) { if (content != myContentManager.getSelectedContent()) { - myContentManager.removeContentManagerListener(myContentManagerListener); - myContentManager.setSelectedContent(content); - myContentManager.addContentManagerListener(myContentManagerListener); + Content toSelect = content; + // Invoke content selection change later after currently selected content lost a focus. + SwingUtilities.invokeLater(() -> { + if (myContentManager.isDisposed() || myContentManager.getIndexOfContent(toSelect) == -1) return; + + myContentManager.removeContentManagerListener(myContentManagerListener); + myContentManager.setSelectedContent(toSelect); + myContentManager.addContentManagerListener(myContentManagerListener); + }); } showContentPanel(); return; From bf654336c97e7da4b3d2ffd682baa00abe2c0c59 Mon Sep 17 00:00:00 2001 From: Olga Strizhenko Date: Wed, 25 Oct 2017 14:10:30 +0300 Subject: [PATCH 05/46] Spellchecker: remove pdflib specific words --- .../com/intellij/spellchecker/jetbrains.dic | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index 03cea3364fc9..9188987875c2 100644 --- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -18,7 +18,6 @@ argv arial arity arquillian -asciifile asensitive aspectj async @@ -35,7 +34,6 @@ autoextend autoincrement autorelease autorotate -autospace backend backref backtrace @@ -76,10 +74,8 @@ cglib chai changelog changelist -charref charset charsets -charspacing checkbox checkboxes checkstyle @@ -126,8 +122,6 @@ covariant cplusplus cron ctrl -currentx -currenty customizer customizers cyclomatic @@ -179,8 +173,6 @@ endif enum enums eqeqeq -errorpolicy -escapesequence eval evex exif @@ -190,7 +182,6 @@ externalizer facebook facelet facelets -fakebold fallthrough fastcall favicon @@ -199,15 +190,12 @@ fileset filesets filesystem filesystems -fillrule finalizer finalizers findbugs firefox fixme foldr -fontname -fontsize foreach formatter freelist @@ -234,7 +222,6 @@ gists github gitlab globals -glyphcheck google grapheme gruntfile @@ -257,9 +244,6 @@ hazelcast hdiv helvetica holdability -honoriccprofile -honorlang -horizscaling hostname hprof href @@ -268,17 +252,8 @@ hsqldb html http https -hypertextencoding -hypertextformat -icccomponents -iccprofile -iccprofilecmyk -iccprofilegray -iccprofilergb iconable iife -imageheight -imagewidth impl implementor implementors @@ -307,7 +282,6 @@ iphone iphoneos isnan isnull -italicangle jacoco javabean javabeans @@ -351,7 +325,6 @@ lcovonly ldap lexing libxml -licensefile lifecycle likec linestring @@ -365,7 +338,6 @@ localtime localtimestamp logfile login -logmsg logoff logon logout @@ -385,7 +357,6 @@ makefiles malloc maxdatafiles maxextents -maxfilehandles maximizable maxinstances maxlogfiles @@ -449,7 +420,6 @@ noclone nocommon nocreate nocycle -nodemostamp noduplicate noexcept nodegroup @@ -501,12 +471,9 @@ opensymphony optnone osgi outfile -overline overrider overriders pageable -pageheight -pagewidth param parameterizable params @@ -519,7 +486,6 @@ pctincrease pctthreshold pctused pctversion -pdflib permalink petersburg pipelined @@ -559,7 +525,6 @@ prepended prepends preprocessor preprocessors -preserveoldpantonenames println processlist profiler @@ -602,7 +567,6 @@ reimport reindex reindexing renderer -renderingintent repackager replacer repo @@ -612,9 +576,6 @@ resetlogs resizable resize resizeable -resourcefile -resx -resy rethrow rethrowing rethrown @@ -644,7 +605,6 @@ serializers servererror servlet servlets -setcolor severities sfinae sftp @@ -694,7 +654,6 @@ sourcecode sourceforge spellchecker spellchecking -spotcolorlookup sqlcode sqlerror sqlexception @@ -753,11 +712,6 @@ taglib teamcity templatemode temptable -textformat -textrendering -textrise -textx -texty thiscall throwable thymeleaf @@ -776,7 +730,6 @@ toolset toolsets tooltip tooltips -topdown toplink trebuchet trie @@ -797,8 +750,6 @@ uncommented uncommenting uncurry undef -underlineposition -underlinewidth underwave undoable undofile @@ -815,8 +766,6 @@ uploader upsource urlencoded urowid -usehypertextencoding -usercoordinates username utf util @@ -835,7 +784,6 @@ varray vectorcall verdana versa -versioning vertices viewlet viewport @@ -856,7 +804,6 @@ wiki wildcard wildcards wildfly -wordspacing wordwrap workflow writeln From 094aec6946eb77fcaef6af0be7896c426d7e9b54 Mon Sep 17 00:00:00 2001 From: pasynkov Date: Tue, 24 Oct 2017 19:12:40 +0300 Subject: [PATCH 06/46] register extension for extension point (for Upsource) (cherry picked from commit 5076526) --- .../openapi/extensions/ExtensionsArea.java | 1 + .../extensions/impl/ExtensionsAreaImpl.java | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java index 7d8de145001c..54701d419800 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java @@ -44,6 +44,7 @@ public interface ExtensionsArea { void registerExtensionPoint(@NotNull PluginDescriptor pluginDescriptor, @NotNull Element extensionPointElement); void registerExtension(@NotNull PluginDescriptor pluginDescriptor, @NotNull Element extensionElement, String ns); + void registerExtension(@NotNull final ExtensionPoint extensionPoint, @NotNull final PluginDescriptor pluginDescriptor, @NotNull final Element extensionElement); String getAreaClass(); } diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java index 929eedf935dc..df2c54b5bd12 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java @@ -155,6 +155,29 @@ public class ExtensionsAreaImpl implements ExtensionsArea { extensionPoint.registerExtensionAdapter(adapter); } + // Used in Upsource + @Override + public void registerExtension(@NotNull final ExtensionPoint extensionPoint, @NotNull final PluginDescriptor pluginDescriptor, @NotNull final Element extensionElement) { + if (!Extensions.isComponentSuitableForOs(extensionElement.getAttributeValue("os"))) { + return; + } + + ExtensionComponentAdapter adapter; + if (extensionPoint.getKind() == ExtensionPoint.Kind.INTERFACE) { + String implClass = extensionElement.getAttributeValue("implementation"); + if (implClass == null) { + throw new RuntimeException("'implementation' attribute not specified for '" + extensionPoint.getName() + "' extension in '" + pluginDescriptor.getPluginId() + .getIdString() + "' plugin"); + } + adapter = new ExtensionComponentAdapter(implClass, extensionElement, myPicoContainer, pluginDescriptor, shouldDeserializeInstance(extensionElement)); + } + else { + adapter = new ExtensionComponentAdapter(extensionPoint.getClassName(), extensionElement, myPicoContainer, pluginDescriptor, true); + } + myPicoContainer.registerComponent(adapter); + ((ExtensionPointImpl)extensionPoint).registerExtensionAdapter(adapter); + } + private static boolean shouldDeserializeInstance(Element extensionElement) { // has content if (!extensionElement.getContent().isEmpty()) return true; From d3e7348496aa5a46f325bbd09a62ac2132c2c456 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 25 Oct 2017 14:30:21 +0300 Subject: [PATCH 07/46] platform cleanup: remove duplicated code from ExtensionsAreaImpl --- .../extensions/impl/ExtensionsAreaImpl.java | 26 +++---------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java index df2c54b5bd12..2af63840201f 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java @@ -131,28 +131,8 @@ public class ExtensionsAreaImpl implements ExtensionsArea { @Override public void registerExtension(@NotNull final PluginDescriptor pluginDescriptor, @NotNull final Element extensionElement, String ns) { - final PluginId pluginId = pluginDescriptor.getPluginId(); - - if (!Extensions.isComponentSuitableForOs(extensionElement.getAttributeValue("os"))) { - return; - } - String epName = extractEPName(extensionElement, ns); - - ExtensionComponentAdapter adapter; - final ExtensionPointImpl extensionPoint = getExtensionPoint(epName); - if (extensionPoint.getKind() == ExtensionPoint.Kind.INTERFACE) { - String implClass = extensionElement.getAttributeValue("implementation"); - if (implClass == null) { - throw new RuntimeException("'implementation' attribute not specified for '" + epName + "' extension in '" + pluginId.getIdString() + "' plugin"); - } - adapter = new ExtensionComponentAdapter(implClass, extensionElement, myPicoContainer, pluginDescriptor, shouldDeserializeInstance(extensionElement)); - } - else { - adapter = new ExtensionComponentAdapter(extensionPoint.getClassName(), extensionElement, myPicoContainer, pluginDescriptor, true); - } - myPicoContainer.registerComponent(adapter); - extensionPoint.registerExtensionAdapter(adapter); + registerExtension(getExtensionPoint(epName), pluginDescriptor, extensionElement); } // Used in Upsource @@ -166,8 +146,8 @@ public class ExtensionsAreaImpl implements ExtensionsArea { if (extensionPoint.getKind() == ExtensionPoint.Kind.INTERFACE) { String implClass = extensionElement.getAttributeValue("implementation"); if (implClass == null) { - throw new RuntimeException("'implementation' attribute not specified for '" + extensionPoint.getName() + "' extension in '" + pluginDescriptor.getPluginId() - .getIdString() + "' plugin"); + throw new RuntimeException("'implementation' attribute not specified for '" + extensionPoint.getName() + "' extension in '" + + pluginDescriptor.getPluginId().getIdString() + "' plugin"); } adapter = new ExtensionComponentAdapter(implClass, extensionElement, myPicoContainer, pluginDescriptor, shouldDeserializeInstance(extensionElement)); } From 4146c9c0e1703c8b224c27977b301b421289459f Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Wed, 25 Oct 2017 18:37:28 +0700 Subject: [PATCH 08/46] WrapWithAdapterMethodCallFix: LambdaUtil#notInferredType used Review ID: IDEA-CR-25945 --- .../daemon/impl/quickfix/WrapWithAdapterMethodCallFix.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapWithAdapterMethodCallFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapWithAdapterMethodCallFix.java index f4cbb518aea2..d37247be06b3 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapWithAdapterMethodCallFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/WrapWithAdapterMethodCallFix.java @@ -64,10 +64,7 @@ public class WrapWithAdapterMethodCallFix extends LocalQuickFixAndIntentionActio return false; } PsiType variableType = GenericsUtil.getVariableTypeByExpressionType(inType); - if(variableType instanceof PsiLambdaExpressionType || variableType instanceof PsiMethodReferenceType - || variableType instanceof PsiLambdaParameterType) { - return false; - } + if (LambdaUtil.notInferredType(variableType)) return false; String typeText = variableType.getCanonicalText(); PsiExpression replacement = createReplacement(context, "((" + typeText + ")null)"); From aa64f2247c6c4b293ff8965f59abcf883e9c539f Mon Sep 17 00:00:00 2001 From: Kirill Kirichenko Date: Wed, 25 Oct 2017 15:01:36 +0300 Subject: [PATCH 09/46] IDEA-181171 Test progress should green/red according to the result of the tests --- .../laf/darcula/ui/DarculaProgressBarUI.java | 43 ++++++++++--------- .../status/ShowProgressTestDialogAction.java | 22 +++++----- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaProgressBarUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaProgressBarUI.java index 42a4af3453a8..ae2179cf02fc 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaProgressBarUI.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaProgressBarUI.java @@ -15,6 +15,7 @@ */ package com.intellij.ide.ui.laf.darcula.ui; +import com.intellij.openapi.progress.util.ColorProgressBar; import com.intellij.ui.Gray; import com.intellij.ui.JBColor; import com.intellij.util.ui.JBInsets; @@ -36,16 +37,14 @@ public class DarculaProgressBarUI extends BasicProgressBarUI { private static final Color REMAINDER_COLOR = new JBColor(Gray.xC4, Gray.x69); private static final Color FINISHED_COLOR = new JBColor(Gray.x80, Gray.xA0); - private static final Color ERROR_COLOR = new JBColor(new Color(0xd80000), new Color(0xff4053)); - private static final Color SUCCESS_COLOR = new JBColor(new Color(0x34b171), new Color(0x008f50)); - private static final Color START_COLOR = new JBColor(Gray.xC4, Gray.x69); private static final Color END_COLOR = new JBColor(Gray.x80, Gray.x83); - private static final Color ERROR_START_COLOR = new JBColor(new Color(0xFB8F89), new Color(0xf4a2a0)); - private static final Color ERROR_END_COLOR = ERROR_COLOR; - private static final Color SUCCESS_START_COLOR = new JBColor(new Color(0x7EE8A5), new Color(0x5dc48f)); - private static final Color SUCCESS_END_COLOR = SUCCESS_COLOR; + private static final Color RED = new JBColor(new Color(0xd80000), new Color(0xff4053)); + private static final Color RED_LIGHT = new JBColor(new Color(0xFB8F89), new Color(0xf4a2a0)); + + private static final Color GREEN = new JBColor(new Color(0x34b171), new Color(0x008f50)); + private static final Color GREEN_LIGHT = new JBColor(new Color(0x7EE8A5), new Color(0x5dc48f)); private static final int STEP = 6; @@ -78,15 +77,16 @@ public class DarculaProgressBarUI extends BasicProgressBarUI { JBInsets.removeFrom(r, i); int orientation = progressBar.getOrientation(); - // Detect gradient color + // Use foreground color as a reference, don't use it directly. This is done for compatibility reason. + // Colors are hardcoded in UI delegates by design. If more colors are needed contact designers. Color startColor, endColor; - String type = (String)progressBar.getClientProperty("ProgressBar.color"); - if ("error".equals(type)) { - startColor = ERROR_START_COLOR; - endColor = ERROR_END_COLOR; - } else if ("success".equals(type)) { - startColor = SUCCESS_START_COLOR; - endColor = SUCCESS_END_COLOR; + Color foreground = progressBar.getForeground(); + if (foreground == ColorProgressBar.RED) { + startColor = RED; + endColor = RED_LIGHT; + } else if (foreground == ColorProgressBar.GREEN) { + startColor = GREEN; + endColor = GREEN_LIGHT; } else { startColor = getStartColor(); endColor = getEndColor(); @@ -206,12 +206,13 @@ public class DarculaProgressBarUI extends BasicProgressBarUI { g2.setColor(getRemainderColor()); g2.fill(fullShape); - - String type = (String)progressBar.getClientProperty("ProgressBar.color"); - if ("error".equals(type)) { - g2.setColor(ERROR_COLOR); - } else if ("success".equals(type)) { - g2.setColor(SUCCESS_COLOR); + // Use foreground color as a reference, don't use it directly. This is done for compatibility reason. + // Colors are hardcoded in UI delegates by design. If more colors are needed contact designers. + Color foreground = progressBar.getForeground(); + if (foreground == ColorProgressBar.RED) { + g2.setColor(RED); + } else if (foreground == ColorProgressBar.GREEN) { + g2.setColor(GREEN); } else { g2.setColor(getFinishedColor()); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ShowProgressTestDialogAction.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ShowProgressTestDialogAction.java index 05777a58689a..5158e0f608dc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ShowProgressTestDialogAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ShowProgressTestDialogAction.java @@ -18,6 +18,7 @@ package com.intellij.openapi.wm.impl.status; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.progress.util.ColorProgressBar; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -25,6 +26,7 @@ import com.intellij.util.Alarm; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.*; import java.util.ArrayList; import java.util.List; @@ -49,17 +51,17 @@ public class ShowProgressTestDialogAction extends AnAction implements DumbAware panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); panel.add(createPanel(false, null, false)); - panel.add(createPanel(false, "error", false)); - panel.add(createPanel(false, "success", false)); + panel.add(createPanel(false, ColorProgressBar.RED, false)); + panel.add(createPanel(false, ColorProgressBar.GREEN, false)); panel.add(createPanel(false, null, true)); - panel.add(createPanel(false, "error", true)); - panel.add(createPanel(false, "success", true)); + panel.add(createPanel(false, ColorProgressBar.RED, true)); + panel.add(createPanel(false, ColorProgressBar.GREEN, true)); panel.add(createPanel(true, null, false)); panel.add(createPanel(true, null, true)); - panel.add(createPanel(true, "error", false)); - panel.add(createPanel(true, "success", false)); - panel.add(createPanel(true, "error", true)); - panel.add(createPanel(true, "success", true)); + panel.add(createPanel(true, ColorProgressBar.RED, false)); + panel.add(createPanel(true, ColorProgressBar.GREEN, false)); + panel.add(createPanel(true, ColorProgressBar.RED, true)); + panel.add(createPanel(true, ColorProgressBar.GREEN, true)); for(JProgressBar pb : pbList) { if (!pb.isIndeterminate()) { @@ -78,14 +80,14 @@ public class ShowProgressTestDialogAction extends AnAction implements DumbAware return panel; } - private JComponent createPanel(boolean indeterminate, String colorType, boolean modeless) { + private JComponent createPanel(boolean indeterminate, Color foreground, boolean modeless) { String text = (indeterminate ? "indeterminate" : "determinate"); JLabel label = new JLabel(text); JProgressBar progress = new JProgressBar(0, 100); progress.setIndeterminate(indeterminate); progress.setValue(0); - progress.putClientProperty("ProgressBar.color", colorType); + progress.setForeground(foreground); progress.putClientProperty("ProgressBar.modeless", Boolean.valueOf(modeless)); JPanel panel = new JPanel(); From 792cb3977fd001240999f847da70492a3fd3776b Mon Sep 17 00:00:00 2001 From: Konstantin Aleev Date: Wed, 25 Oct 2017 14:07:08 +0300 Subject: [PATCH 10/46] RunDashboard: update status labels and icons --- .../dashboard/RunDashboardRunConfigurationStatus.java | 10 ++++++---- .../execution/dashboard/tree/RunConfigurationNode.java | 10 ++++++++-- .../src/messages/ExecutionBundle.properties | 5 +++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardRunConfigurationStatus.java b/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardRunConfigurationStatus.java index a50212887828..d0388b7b7019 100644 --- a/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardRunConfigurationStatus.java +++ b/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardRunConfigurationStatus.java @@ -27,11 +27,13 @@ import javax.swing.*; */ public class RunDashboardRunConfigurationStatus { public static final RunDashboardRunConfigurationStatus STARTED = new RunDashboardRunConfigurationStatus( - ExecutionBundle.message("run.dashboard.started.group.name"), AllIcons.Toolwindows.ToolWindowRun); - public static final RunDashboardRunConfigurationStatus STOPPED = new RunDashboardRunConfigurationStatus( - ExecutionBundle.message("run.dashboard.stopped.group.name"), AllIcons.Actions.Suspend); + ExecutionBundle.message("run.dashboard.started.group.name"), AllIcons.Actions.Execute); public static final RunDashboardRunConfigurationStatus FAILED = new RunDashboardRunConfigurationStatus( ExecutionBundle.message("run.dashboard.failed.group.name"), AllIcons.General.Error); + public static final RunDashboardRunConfigurationStatus STOPPED = new RunDashboardRunConfigurationStatus( + ExecutionBundle.message("run.dashboard.stopped.group.name"), AllIcons.Actions.Restart); + public static final RunDashboardRunConfigurationStatus CONFIGURED = new RunDashboardRunConfigurationStatus( + ExecutionBundle.message("run.dashboard.configured.group.name"), AllIcons.General.Settings); private final String myName; private final Icon myIcon; @@ -52,7 +54,7 @@ public class RunDashboardRunConfigurationStatus { public static RunDashboardRunConfigurationStatus getStatus(RunDashboardRunConfigurationNode node) { RunContentDescriptor descriptor = node.getDescriptor(); if (descriptor == null) { - return STOPPED; + return CONFIGURED; } ProcessHandler processHandler = descriptor.getProcessHandler(); if (processHandler == null) { diff --git a/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunConfigurationNode.java b/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunConfigurationNode.java index 81fedc955995..2143884b5954 100644 --- a/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunConfigurationNode.java +++ b/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunConfigurationNode.java @@ -80,8 +80,14 @@ class RunConfigurationNode extends AbstractTreeNode Date: Wed, 25 Oct 2017 15:11:38 +0300 Subject: [PATCH 11/46] RunDashboard: grouping rules may provide comparator for groups ordering --- .../dashboard/RunDashboardGroupingRule.java | 6 ++++++ .../RunDashboardRunConfigurationStatus.java | 16 +++++++++++----- .../dashboard/tree/RunDashboardGroupImpl.java | 7 +++++++ .../tree/RunDashboardTreeStructure.java | 2 +- .../tree/StatusDashboardGroupingRule.java | 8 ++++++++ 5 files changed, 33 insertions(+), 6 deletions(-) diff --git a/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardGroupingRule.java b/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardGroupingRule.java index 6c1726ff8406..163d5ca983b3 100644 --- a/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardGroupingRule.java +++ b/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardGroupingRule.java @@ -35,6 +35,8 @@ public interface RunDashboardGroupingRule extends TreeAction { return res != 0 ? res : (o1.getName().compareTo(o2.getName())); }; + Comparator GROUP_NAME_COMPARATOR = Comparator.comparing(RunDashboardGroup::getName); + /** * Grouping rules are ordered and applied to dashboard nodes according to their priority. * The higher the priority, the higher groups produced by this rule are presented in the dashboard tree. @@ -60,6 +62,10 @@ public interface RunDashboardGroupingRule extends TreeAction { @Nullable RunDashboardGroup getGroup(AbstractTreeNode node); + default Comparator getGroupComparator() { + return GROUP_NAME_COMPARATOR; + } + interface Priorities { int BY_RUN_CONFIG = 200; int BY_FOLDER = 400; diff --git a/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardRunConfigurationStatus.java b/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardRunConfigurationStatus.java index d0388b7b7019..1fc56349a63b 100644 --- a/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardRunConfigurationStatus.java +++ b/platform/lang-api/src/com/intellij/execution/dashboard/RunDashboardRunConfigurationStatus.java @@ -27,20 +27,22 @@ import javax.swing.*; */ public class RunDashboardRunConfigurationStatus { public static final RunDashboardRunConfigurationStatus STARTED = new RunDashboardRunConfigurationStatus( - ExecutionBundle.message("run.dashboard.started.group.name"), AllIcons.Actions.Execute); + ExecutionBundle.message("run.dashboard.started.group.name"), AllIcons.Actions.Execute, 10); public static final RunDashboardRunConfigurationStatus FAILED = new RunDashboardRunConfigurationStatus( - ExecutionBundle.message("run.dashboard.failed.group.name"), AllIcons.General.Error); + ExecutionBundle.message("run.dashboard.failed.group.name"), AllIcons.General.Error, 20); public static final RunDashboardRunConfigurationStatus STOPPED = new RunDashboardRunConfigurationStatus( - ExecutionBundle.message("run.dashboard.stopped.group.name"), AllIcons.Actions.Restart); + ExecutionBundle.message("run.dashboard.stopped.group.name"), AllIcons.Actions.Restart, 30); public static final RunDashboardRunConfigurationStatus CONFIGURED = new RunDashboardRunConfigurationStatus( - ExecutionBundle.message("run.dashboard.configured.group.name"), AllIcons.General.Settings); + ExecutionBundle.message("run.dashboard.configured.group.name"), AllIcons.General.Settings, 40); private final String myName; private final Icon myIcon; + private final int myPriority; - public RunDashboardRunConfigurationStatus(String name, Icon icon) { + public RunDashboardRunConfigurationStatus(String name, Icon icon, int priority) { myName = name; myIcon = icon; + myPriority = priority; } public String getName() { @@ -51,6 +53,10 @@ public class RunDashboardRunConfigurationStatus { return myIcon; } + public int getPriority() { + return myPriority; + } + public static RunDashboardRunConfigurationStatus getStatus(RunDashboardRunConfigurationNode node) { RunContentDescriptor descriptor = node.getDescriptor(); if (descriptor == null) { diff --git a/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunDashboardGroupImpl.java b/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunDashboardGroupImpl.java index b3e2c8eff4c1..ee612d6dc873 100644 --- a/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunDashboardGroupImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunDashboardGroupImpl.java @@ -33,6 +33,10 @@ public class RunDashboardGroupImpl implements RunDashboardGroup { myIcon = icon; } + public T getValue() { + return myValue; + } + @Override public String getName() { return myName; @@ -50,6 +54,9 @@ public class RunDashboardGroupImpl implements RunDashboardGroup { @Override public final boolean equals(Object obj) { + if (this == obj) { + return true; + } if (obj instanceof RunDashboardGroupImpl) { return myValue.equals(((RunDashboardGroupImpl)obj).myValue); } diff --git a/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunDashboardTreeStructure.java b/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunDashboardTreeStructure.java index 1f9cf5267ef2..5e9efb27ff88 100644 --- a/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunDashboardTreeStructure.java +++ b/platform/lang-impl/src/com/intellij/execution/dashboard/tree/RunDashboardTreeStructure.java @@ -138,7 +138,7 @@ public class RunDashboardTreeStructure extends AbstractTreeStructureBase { }); } else { - Collections.sort(result, Comparator.comparing(node -> ((GroupingNode)node).getGroup().getName())); + Collections.sort(result, Comparator.comparing(node -> ((GroupingNode)node).getGroup(), rule.getGroupComparator())); result.addAll(ungroupedNodes); } return result; diff --git a/platform/lang-impl/src/com/intellij/execution/dashboard/tree/StatusDashboardGroupingRule.java b/platform/lang-impl/src/com/intellij/execution/dashboard/tree/StatusDashboardGroupingRule.java index 3b7c8d737eaa..eb76f8b0ef30 100644 --- a/platform/lang-impl/src/com/intellij/execution/dashboard/tree/StatusDashboardGroupingRule.java +++ b/platform/lang-impl/src/com/intellij/execution/dashboard/tree/StatusDashboardGroupingRule.java @@ -25,6 +25,8 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Comparator; + /** * @author konstantin.aleev */ @@ -72,4 +74,10 @@ public class StatusDashboardGroupingRule implements RunDashboardGroupingRule { } return null; } + + @Override + public Comparator getGroupComparator() { + //noinspection unchecked + return Comparator.comparing(group -> ((RunDashboardGroupImpl)group).getValue().getPriority()); + } } From b3b3efe4b1f800790a85b4165dea404dceae1b88 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 25 Oct 2017 13:39:25 +0200 Subject: [PATCH 12/46] IG: warn on '==' if no common subclass is found (IDEA-178449) --- ...lsBetweenInconvertibleTypesInspection.java | 77 +++++++++++++------ ...tweenInconvertibleTypesInspectionTest.java | 28 ++++--- 2 files changed, 65 insertions(+), 40 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspection.java index bfdbcafc82b7..6e3147a3dcac 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspection.java @@ -16,10 +16,8 @@ package com.siyeh.ig.bugs; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReferenceExpression; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; @@ -76,27 +74,56 @@ public class EqualsBetweenInconvertibleTypesInspection extends BaseInspection { @Override public BaseInspectionVisitor buildVisitor() { - return new BaseEqualsVisitor() { - void checkTypes(@NotNull PsiReferenceExpression expression, @NotNull PsiType leftType, @NotNull PsiType rightType) { - boolean convertible = TypeUtils.areConvertible(leftType, rightType); - if (convertible) { - if (!WARN_IF_NO_MUTUAL_SUBCLASS_FOUND) return; - if (leftType.isAssignableFrom(rightType) || rightType.isAssignableFrom(leftType)) return; - PsiClass leftClass = PsiUtil.resolveClassInClassTypeOnly(leftType); - PsiClass rightClass = PsiUtil.resolveClassInClassTypeOnly(rightType); - if (leftClass == null || rightClass == null) return; - if (!leftClass.isInterface() && !rightClass.isInterface()) return; - if (!rightClass.isInterface()) { - PsiClass tmp = leftClass; - leftClass = rightClass; - rightClass = tmp; - } - if (InheritanceUtil.existsMutualSubclass(leftClass, rightClass, isOnTheFly())) return; - } - if (TypeUtils.mayBeEqualByContract(leftType, rightType)) return; - PsiElement name = expression.getReferenceNameElement(); - registerError(name == null ? expression : name, leftType, rightType, convertible); + return new EqualsBetweenInconvertibleTypesVisitor(); + } + + private class EqualsBetweenInconvertibleTypesVisitor extends BaseEqualsVisitor { + + @Override + public void visitBinaryExpression(PsiBinaryExpression expression) { + super.visitBinaryExpression(expression); + if (!WARN_IF_NO_MUTUAL_SUBCLASS_FOUND) return; + final IElementType tokenType = expression.getOperationTokenType(); + if (!tokenType.equals(JavaTokenType.EQEQ) && !tokenType.equals(JavaTokenType.NE)) { + return; } - }; + final PsiExpression lhs = expression.getLOperand(); + final PsiType lhsType = lhs.getType(); + final PsiExpression rhs = expression.getROperand(); + if (rhs == null) { + return; + } + final PsiType rhsType = rhs.getType(); + if (lhsType == null || rhsType == null || !TypeUtils.areConvertible(lhsType, rhsType)) { + // red code + return; + } + if (existsSharedSubclass(lhsType, rhsType)) { + return; + } + registerError(expression.getOperationSign(), lhsType, rhsType, true); + } + + void checkTypes(@NotNull PsiReferenceExpression expression, @NotNull PsiType leftType, @NotNull PsiType rightType) { + boolean convertible = TypeUtils.areConvertible(leftType, rightType); + if (convertible && (!WARN_IF_NO_MUTUAL_SUBCLASS_FOUND || existsSharedSubclass(leftType, rightType))) return; + if (TypeUtils.mayBeEqualByContract(leftType, rightType)) return; + PsiElement name = expression.getReferenceNameElement(); + registerError(name == null ? expression : name, leftType, rightType, convertible); + } + + private boolean existsSharedSubclass(@NotNull PsiType leftType, @NotNull PsiType rightType) { + if (leftType.isAssignableFrom(rightType) || rightType.isAssignableFrom(leftType)) return true; + PsiClass leftClass = PsiUtil.resolveClassInClassTypeOnly(leftType); + PsiClass rightClass = PsiUtil.resolveClassInClassTypeOnly(rightType); + if (leftClass == null || rightClass == null) return true; + if (!leftClass.isInterface() && !rightClass.isInterface()) return true; + if (!rightClass.isInterface()) { + PsiClass tmp = leftClass; + leftClass = rightClass; + rightClass = tmp; + } + return InheritanceUtil.existsMutualSubclass(leftClass, rightClass, isOnTheFly()); + } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspectionTest.java index e024c70ef152..b7441f59a552 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/EqualsBetweenInconvertibleTypesInspectionTest.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.siyeh.ig.bugs; import com.intellij.codeInspection.InspectionProfileEntry; @@ -102,6 +88,18 @@ public class EqualsBetweenInconvertibleTypesInspectionTest extends LightInspecti "}"); } + public void testNoCommonSubclassEqualityComparison() { + doTest("import java.util.Date;\n" + + "import java.util.Map;\n" + + "import java.util.Objects;\n" + + "\n" + + "class X {\n" + + " public static boolean foo(Date date, Map map) {\n" + + " return map /*No class found which is a subtype of both 'Map' and 'Date'*/==/**/ date;\n" + + " }\n" + + "}"); + } + public void testCommonSubclass() { doTest("import java.util.Date;\n" + "import java.util.Map;\n" + From d1ac34da2119b0c8e9a8f19f70630af188ce5b80 Mon Sep 17 00:00:00 2001 From: Andrey Vokin Date: Wed, 25 Oct 2017 14:21:56 +0200 Subject: [PATCH 13/46] Fix NPE when Cucumber Java step fail but error message is null --- .../plugins/cucumber/java/run/CucumberJvmSMFormatterUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatterUtil.java b/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatterUtil.java index c201cafdf31b..ead4a8e5518b 100644 --- a/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatterUtil.java +++ b/plugins/cucumber-jvm-formatter/src/org/jetbrains/plugins/cucumber/java/run/CucumberJvmSMFormatterUtil.java @@ -38,6 +38,9 @@ public class CucumberJvmSMFormatterUtil { } public static String escape(String source) { + if (source == null) { + return ""; + } return source.replace("|", "||").replace("\n", "|n").replace("\r", "|r").replace("'", "|'").replace("[", "|[").replace("]", "|]"); } } From e3df5ec32f1b70abcbeca8d6c8cc20d34cd424e0 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Wed, 25 Oct 2017 15:34:24 +0300 Subject: [PATCH 14/46] Java: Don't count overlapping fragments as duplicates - cleanup after review (IDEA-180824) --- .../intellij/refactoring/util/duplicates/DuplicatesFinder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java index 8dfb0c7bc981..fd187e4af5a1 100644 --- a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java +++ b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java @@ -196,7 +196,7 @@ public class DuplicatesFinder { ArrayList candidates = new ArrayList<>(); for (final PsiElement element : myPattern) { if (sibling == null) return null; - if (!canBeEquivalent(element, sibling) || sibling != candidate && isSelf(sibling)) return null; + if (!canBeEquivalent(element, sibling) || isSelf(sibling)) return null; candidates.add(sibling); sibling = PsiTreeUtil.skipSiblingsForward(sibling, PsiWhiteSpace.class, PsiComment.class, PsiEmptyStatement.class); } From 6f3cf388f99588725a27c5d33152febbcf9ae0f5 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 25 Oct 2017 15:36:14 +0300 Subject: [PATCH 15/46] IDEA-181019 Error when doing a 'find usage' with 'derived class' selected in dialog --- platform/core-api/src/com/intellij/usageView/UsageInfo.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/core-api/src/com/intellij/usageView/UsageInfo.java b/platform/core-api/src/com/intellij/usageView/UsageInfo.java index 15e6e0611d81..3a767a71bc8e 100644 --- a/platform/core-api/src/com/intellij/usageView/UsageInfo.java +++ b/platform/core-api/src/com/intellij/usageView/UsageInfo.java @@ -49,8 +49,9 @@ public class UsageInfo { int effectiveEnd; if (startOffset == -1 && endOffset == -1) { // calculate natural element range - effectiveStart = element.getTextOffset() - elementRange.getStartOffset(); - effectiveEnd = elementRange.getLength(); + // Cls element.getTextOffset() returns -1 + effectiveStart = Math.max(0, element.getTextOffset() - elementRange.getStartOffset()); + effectiveEnd = Math.max(effectiveStart, elementRange.getLength()); } else { effectiveStart = startOffset; From de252f1eb25ecfee054c50efb40c3c5fb5b5dfe6 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 25 Oct 2017 15:37:41 +0300 Subject: [PATCH 16/46] Revert(inspections "fatal.errors" failing mysteriously): reuse PersistentFS directory cache to avoid re-creating and retaining VDirs unnecessarily --- .../openapi/vfs/newvfs/impl/VfsData.java | 16 ++++--------- .../newvfs/persistent/PersistentFSImpl.java | 23 ++++--------------- 2 files changed, 10 insertions(+), 29 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsData.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsData.java index 210c55c30024..6179bab49607 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsData.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsData.java @@ -20,8 +20,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.vfs.InvalidVirtualFileAccessException; import com.intellij.openapi.vfs.newvfs.persistent.FSRecords; -import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; -import com.intellij.openapi.vfs.newvfs.persistent.PersistentFSImpl; import com.intellij.util.ArrayUtil; import com.intellij.util.concurrency.AtomicFieldUpdater; import com.intellij.util.containers.ConcurrentBitSet; @@ -64,12 +62,12 @@ import static com.intellij.util.ObjectUtils.assertNotNull; * and creates the file instance. See {@link #initFile} * * 3. After that the file is live, an object representing it can be retrieved any time from its parent. File system roots are - * kept on hard references in {@link PersistentFS} + * kept on hard references in {@link com.intellij.openapi.vfs.newvfs.persistent.PersistentFS} * * 4. If a file is deleted (invalidated), then its data is not needed anymore, and should be removed. But this can only happen after * all the listener have been notified about the file deletion and have had their chance to look at the data the last time. See {@link #killInvalidatedFiles()} * - * 5. The file with removed data is marked as "dead" (see {@link #ourDeadMarker}, any access to it will throw {@link InvalidVirtualFileAccessException} + * 5. The file with removed data is marked as "dead" (see {@link #ourDeadMarker}, any access to it will throw {@link com.intellij.openapi.vfs.InvalidVirtualFileAccessException} * Dead ids won't be reused in the same session of the IDE. * * @author peter @@ -112,11 +110,7 @@ public class VfsData { } @Nullable - static VirtualFileSystemEntry getFileById(int id, @NotNull VirtualDirectoryImpl parent) { - PersistentFSImpl persistentFS = (PersistentFSImpl)PersistentFS.getInstance(); - VirtualFileSystemEntry dir = persistentFS.getCachedDir(id); - if (dir != null) return dir; - + static VirtualFileSystemEntry getFileById(int id, VirtualDirectoryImpl parent) { Segment segment = getSegment(id, false); if (segment == null) return null; @@ -133,7 +127,7 @@ public class VfsData { throw new AssertionError("nameId=" + nameId + "; data=" + o + "; parent=" + parent + "; parent.id=" + parent.getId() + "; db.parent=" + FSRecords.getParent(id)); } - return o instanceof DirectoryData ? persistentFS.getOrCacheDir(id, segment, (DirectoryData)o, parent) + return o instanceof DirectoryData ? new VirtualDirectoryImpl(id, segment, (DirectoryData)o, parent, parent.getFileSystem()) : new VirtualFileImpl(id, segment, parent); } @@ -279,7 +273,7 @@ public class VfsData { private Set myAdoptedNames; // guarded by this @NotNull - VirtualFileSystemEntry[] getFileChildren(int fileId, @NotNull VirtualDirectoryImpl parent) { + VirtualFileSystemEntry[] getFileChildren(int fileId, VirtualDirectoryImpl parent) { assert fileId > 0; VirtualFileSystemEntry[] children = new VirtualFileSystemEntry[myChildrenIds.length]; for (int i = 0; i < myChildrenIds.length; i++) { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java index d99fbf713dc7..175abdb2deab 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java @@ -69,7 +69,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone private final ConcurrentIntObjectMap myRootsById = ContainerUtil.createConcurrentIntObjectMap(10, 0.4f, JobSchedulerImpl.CORES_COUNT); // FS roots must be in this map too. findFileById() relies on this. - private final ConcurrentIntObjectMap myIdToDirCache = ContainerUtil.createConcurrentIntObjectSoftValueMap(); + private final ConcurrentIntObjectMap myIdToDirCache = ContainerUtil.createConcurrentIntObjectMap(); private final Object myInputLock = new Object(); private final AtomicBoolean myShutDown = new AtomicBoolean(false); @@ -121,20 +121,6 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone return FSRecords.getCreationTimestamp(); } - @NotNull - public VirtualFileSystemEntry getOrCacheDir(int id, - @NotNull VfsData.Segment segment, - @NotNull VfsData.DirectoryData o, - @NotNull VirtualDirectoryImpl parent) { - VirtualFileSystemEntry dir = myIdToDirCache.get(id); - if (dir != null) return dir; - dir = new VirtualDirectoryImpl(id, segment, o, parent, parent.getFileSystem()); - return myIdToDirCache.cacheOrGet(id, dir); - } - public VirtualFileSystemEntry getCachedDir(int id) { - return myIdToDirCache.get(id); - } - @NotNull private static NewVirtualFileSystem getDelegate(@NotNull VirtualFile file) { return (NewVirtualFileSystem)file.getFileSystem(); @@ -1053,10 +1039,11 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone @Override public void clearIdCache() { // remove all except myRootsById contents - int[] ids = myIdToDirCache.keys(); - for (int id : ids) { + for (Iterator> iterator = myIdToDirCache.entries().iterator(); iterator.hasNext(); ) { + ConcurrentIntObjectMap.IntEntry entry = iterator.next(); + int id = entry.getKey(); if (!myRootsById.containsKey(id)) { - myIdToDirCache.remove(id); + iterator.remove(); } } } From eac0894f8aa6fbc205dc0ce65f124f04b1e90fae Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 25 Oct 2017 15:44:55 +0300 Subject: [PATCH 17/46] fix test data --- .../quickFix/moveInitializerToSetUp/afterTestNG.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToSetUp/afterTestNG.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToSetUp/afterTestNG.java index 7bfbf5594472..3729879301fc 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToSetUp/afterTestNG.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToSetUp/afterTestNG.java @@ -3,7 +3,7 @@ public class X { int i; @org.testng.annotations.BeforeMethod - public void setUp() throws Exception { + public void setUp() { i = 7; } From 6c37f0c0c868c986e63e87308acf530470adfb1a Mon Sep 17 00:00:00 2001 From: Artem Khvastunov Date: Wed, 25 Oct 2017 14:52:09 +0200 Subject: [PATCH 18/46] Revert "CharSequenceSubSequence fix stupid equals optimisation error" This reverts commit 1358520 --- .../src/com/intellij/util/text/CharSequenceSubSequence.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java b/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java index 19ec628047e2..4c24a2315fe6 100644 --- a/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java +++ b/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java @@ -75,7 +75,7 @@ public class CharSequenceSubSequence implements CharSequence, CharArrayExternali @Override public boolean equals(Object o) { if (this == o) return true; - if (o instanceof CharSequenceSubSequence && hashCode() != o.hashCode()) return false; + if (o instanceof CharSequenceSubSequence) return hashCode() == o.hashCode(); if (o == null || !(o instanceof CharSequence)) return false; return StringUtil.equals(this, (CharSequence)o); } From bef25a8cf361c63d725a3eac4646781109d17f45 Mon Sep 17 00:00:00 2001 From: Artem Khvastunov Date: Wed, 25 Oct 2017 14:52:15 +0200 Subject: [PATCH 19/46] Revert "PHP php variable, parameter etc. name CharSequence memory usage" This reverts commit 9af8d5e --- .../util/text/CharSequenceSubSequence.java | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java b/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java index 4c24a2315fe6..1ab671e84ce2 100644 --- a/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java +++ b/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java @@ -1,16 +1,18 @@ -// Copyright 2000-2017 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. +/* + * Copyright 2000-2016 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; @@ -72,14 +74,6 @@ public class CharSequenceSubSequence implements CharSequence, CharArrayExternali CharArrayUtil.getChars(myChars, dest, start + myStart, destPos, end - start); } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o instanceof CharSequenceSubSequence) return hashCode() == o.hashCode(); - if (o == null || !(o instanceof CharSequence)) return false; - return StringUtil.equals(this, (CharSequence)o); - } - private transient int hash; @Override public int hashCode() { From beddc8b9651a602bee1531bb26e4c11b5a14e0eb Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 24 Oct 2017 12:29:40 +0300 Subject: [PATCH 20/46] Refine text in HidpiInfo --- .../platform-impl/src/com/intellij/internal/HidpiInfo.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/internal/HidpiInfo.java b/platform/platform-impl/src/com/intellij/internal/HidpiInfo.java index a32ebef15a46..55d30db175b9 100644 --- a/platform/platform-impl/src/com/intellij/internal/HidpiInfo.java +++ b/platform/platform-impl/src/com/intellij/internal/HidpiInfo.java @@ -38,8 +38,10 @@ public class HidpiInfo extends AnAction implements DumbAware { private final String JRE_HIDPI_MODE_TEXT = "Per-monitor DPI-aware"; private final String JRE_HIDPI_MODE_DESC = "When enabled, the IDE UI scaling honors per-monitor DPI.
" + + (SystemInfo.isWindows ? "To " + (ENABLED ? "disable" : "enable") + " set the JVM option -Dsun.java2d.uiScale.enabled=" + - (ENABLED ? "false" : "true") + " and restart.
"; + (ENABLED ? "false" : "true") + " and restart." : + "The mode can not be changed on this platform."); private final String SYS_SCALE_TEXT = "Monitor scale"; private final String SYS_SCALE_DESC = From 122bc1f9107c4ecdbd18cf39267b89d17c88211d Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 25 Oct 2017 15:50:51 +0300 Subject: [PATCH 21/46] Fix EditorPaintingPerformanceTest failure com.intellij.openapi.editor.NullGraphics2D.getTransform() is unsupported --- .../util/src/com/intellij/util/ui/JBUI.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/platform/util/src/com/intellij/util/ui/JBUI.java b/platform/util/src/com/intellij/util/ui/JBUI.java index 3914d19dbebd..1235f03257ec 100644 --- a/platform/util/src/com/intellij/util/ui/JBUI.java +++ b/platform/util/src/com/intellij/util/ui/JBUI.java @@ -563,17 +563,22 @@ public class JBUI { * @return the original graphics transform when aligned, otherwise null */ public static AffineTransform alignToIntGrid(@NotNull Graphics2D g) { - AffineTransform tx = g.getTransform(); - double scaleX = tx.getScaleX(); - double scaleY = tx.getScaleY(); - boolean fpsTx = scaleX != (int)scaleX || scaleY != (int)scaleY; - if (fpsTx) { - AffineTransform alignedTx = new AffineTransform(); - alignedTx.translate((int)Math.ceil(tx.getTranslateX() - 0.5), (int)Math.ceil(tx.getTranslateY() - 0.5)); - alignedTx.scale(scaleX, scaleY); - assert tx.getShearX() == 0 && tx.getShearY() == 0; // the shear is ignored - g.setTransform(alignedTx); - return tx; + try { + AffineTransform tx = g.getTransform(); + double scaleX = tx.getScaleX(); + double scaleY = tx.getScaleY(); + boolean fpsTx = scaleX != (int)scaleX || scaleY != (int)scaleY; + if (fpsTx) { + AffineTransform alignedTx = new AffineTransform(); + alignedTx.translate((int)Math.ceil(tx.getTranslateX() - 0.5), (int)Math.ceil(tx.getTranslateY() - 0.5)); + alignedTx.scale(scaleX, scaleY); + assert tx.getShearX() == 0 && tx.getShearY() == 0; // the shear is ignored + g.setTransform(alignedTx); + return tx; + } + } + catch (Exception e) { + LOG.trace(e); } return null; } From 981efcdddfd106f9d62695f6ebc311af66ee8dad Mon Sep 17 00:00:00 2001 From: Vasily Romanikhin Date: Wed, 25 Oct 2017 16:03:45 +0300 Subject: [PATCH 22/46] CPP-744, CPP-6352: remote toolchain support; WSL: getWslVersion() was removed from WSLUtil --- .../src/com/intellij/execution/WSLUtil.java | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/execution/WSLUtil.java b/platform/platform-impl/src/com/intellij/execution/WSLUtil.java index 0d9182918578..630d12dbde14 100644 --- a/platform/platform-impl/src/com/intellij/execution/WSLUtil.java +++ b/platform/platform-impl/src/com/intellij/execution/WSLUtil.java @@ -60,33 +60,8 @@ public class WSLUtil { return StringUtil.isEmpty(localAppDataPath) ? null : localAppDataPath + WSL_ROOT_CHUNK; }); - private static final Pattern WIN_10_VERSION_PATTERN = Pattern.compile(".*(?:\\[Version 10\\.\\d+\\.(\\d+)\\])"); - private static final int READ_VERSION_TIMEOUT = 10000; private static final int RESOLVE_SYMLINK_TIMEOUT = 10000; - /** - * WSL version equals Windows build number - * (https://github.com/Microsoft/BashOnWindows/issues/1728) - */ - private static final AtomicNullableLazyValue ourWSLVersion = AtomicNullableLazyValue.createValue(() -> { - final GeneralCommandLine commandLine = new GeneralCommandLine(ExecUtil.getWindowsShellName(), "/c", "ver"); - - try { - final ProcessOutput result = ExecUtil.execAndGetOutput(commandLine, READ_VERSION_TIMEOUT); - if (result.isTimeout()) return null; - - final String out = result.getStdout().trim(); - final Matcher matcher = WIN_10_VERSION_PATTERN.matcher(out); - if (matcher.find()) { - return matcher.group(1); - } - } - catch (ExecutionException e) { - LOG.warn(e); - } - return null; - }); - /** * @return bash file or null if not exists */ @@ -102,14 +77,6 @@ public class WSLUtil { return getWSLBashFile() != null; } - /** - * @return WSL build number or null if it cannot be determined - */ - @Nullable - public static String getWslVersion() { - return hasWSL() ? ourWSLVersion.getValue() : null; - } - /** * @return Windows-dependent path for a file, pointed by {@code wslPath} in WSL */ From 2dad4d6c869e72a0e0e229de384f142e18ef9ff9 Mon Sep 17 00:00:00 2001 From: Vasily Romanikhin Date: Wed, 25 Oct 2017 16:24:29 +0300 Subject: [PATCH 23/46] CPP-744, CPP-6352: remote toolchain support; WSL: updated WSLUtilTest --- .../testSrc/com/intellij/execution/WSLUtilTest.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/execution/WSLUtilTest.java b/platform/platform-tests/testSrc/com/intellij/execution/WSLUtilTest.java index 660d834be3bf..ba74c87a8137 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/WSLUtilTest.java +++ b/platform/platform-tests/testSrc/com/intellij/execution/WSLUtilTest.java @@ -57,12 +57,6 @@ public class WSLUtilTest { assertEquals(originalWslPath, wslPath); } - @Test - public void testVersion() { - final String version = WSLUtil.getWslVersion(); - assertTrue(WSLUtil.hasWSL() ? version != null : version == null); - } - @Test public void testResolveSymlink() throws Exception { assumeTrue(WSLUtil.hasWSL()); From 75a2b0cd034f3370be6af6f9a5172d6e428ac63c Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Wed, 25 Oct 2017 16:02:25 +0300 Subject: [PATCH 24/46] Support old and new project code style settings in import & command line See also IDEA-164602 --- .../codeStyle/CodeStyleSchemeXmlImporter.java | 20 ++----- .../codeStyle/CodeStyleSettingsLoader.java | 34 +++++++++++- .../importSettings/newProjectSettings.xml | 52 +++++++++++++++++++ .../CodeStyleXmlImporterTest.java | 6 +++ 4 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 platform/platform-tests/testData/codeStyle/importSettings/newProjectSettings.xml diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeXmlImporter.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeXmlImporter.java index 60e1a23a2ba4..a275686505ab 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeXmlImporter.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeXmlImporter.java @@ -51,7 +51,7 @@ public class CodeStyleSchemeXmlImporter extends CodeStyleSettingsLoader implemen @NotNull CodeStyleScheme currentScheme, @NotNull SchemeFactory schemeFactory) throws SchemeImportException { Element rootElement = SchemeImportUtil.loadSchemeDom(selectedFile); - Element schemeRoot = getSchemeRoot(rootElement); + Element schemeRoot = findSchemeRoot(rootElement); final Pair importPair = !ApplicationManager.getApplication().isUnitTestMode() ? ImportSchemeChooserDialog.selectOrCreateTargetScheme(project, currentScheme, schemeFactory, getSchemeName(schemeRoot)) : @@ -75,23 +75,9 @@ public class CodeStyleSchemeXmlImporter extends CodeStyleSettingsLoader implemen } return schemeNameAttr.getValue(); } - - private static Element getSchemeRoot(@NotNull Element rootElement) throws SchemeImportException { - if ("project".equals(rootElement.getName())) { - Element child = rootElement.getChild("component"); - if (child != null && "ProjectCodeStyleSettingsManager".equals(child.getAttributeValue("name"))) { - child = child.getChild("option"); - if (child != null && "PER_PROJECT_SETTINGS".equals(child.getAttributeValue("name"))) { - child = child.getChild("value"); - if (child != null) return child; - } - } - throw new SchemeImportException("Invalid scheme root: " + rootElement.getName()); - } - return rootElement; - } - private CodeStyleScheme readSchemeFromDom(@NotNull Element rootElement, @NotNull CodeStyleScheme scheme) + + private static CodeStyleScheme readSchemeFromDom(@NotNull Element rootElement, @NotNull CodeStyleScheme scheme) throws SchemeImportException { CodeStyleSettings newSettings = new CodeStyleSettings(); loadSettings(rootElement, newSettings); diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSettingsLoader.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSettingsLoader.java index 7e15d41fd691..34060e714774 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSettingsLoader.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSettingsLoader.java @@ -33,13 +33,43 @@ public class CodeStyleSettingsLoader { return settings; } - protected void loadSettings(@NotNull Element rootElement, @NotNull CodeStyleSettings settings) throws SchemeImportException { + protected static void loadSettings(@NotNull Element rootElement, @NotNull CodeStyleSettings settings) throws SchemeImportException { try { - settings.readExternal(rootElement); + settings.readExternal(findSchemeRoot(rootElement)); } catch (InvalidDataException e) { throw new SchemeImportException(ApplicationBundle.message("settings.code.style.import.xml.error.can.not.load", e.getMessage())); } } + protected static Element findSchemeRoot(@NotNull Element rootElement) throws SchemeImportException { + String rootName = rootElement.getName(); + // + // Project code style 172.x and earlier + // + if ("project".equals(rootName)) { + Element child = rootElement.getChild("component"); + if (child != null && "ProjectCodeStyleSettingsManager".equals(child.getAttributeValue("name"))) { + child = child.getChild("option"); + if (child != null && "PER_PROJECT_SETTINGS".equals(child.getAttributeValue("name"))) { + child = child.getChild("value"); + if (child != null) return child; + } + } + throw new SchemeImportException("Invalid scheme root: " + rootName); + } + // + // Project code style 173.x and later + // + else if ("component".equals(rootName)) { + if ("ProjectCodeStyleConfiguration".equals(rootElement.getAttributeValue("name"))) { + Element child = rootElement.getChild("code_scheme"); + if (child != null) { + return child; + } + } + throw new SchemeImportException("Invalid scheme root: " + rootName); + } + return rootElement; + } } diff --git a/platform/platform-tests/testData/codeStyle/importSettings/newProjectSettings.xml b/platform/platform-tests/testData/codeStyle/importSettings/newProjectSettings.xml new file mode 100644 index 000000000000..8f2f8deed955 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/importSettings/newProjectSettings.xml @@ -0,0 +1,52 @@ + + + + \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/ide/codeStyleSettings/CodeStyleXmlImporterTest.java b/platform/platform-tests/testSrc/com/intellij/ide/codeStyleSettings/CodeStyleXmlImporterTest.java index f7bb4eed4400..4e57e0d8352e 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/codeStyleSettings/CodeStyleXmlImporterTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ide/codeStyleSettings/CodeStyleXmlImporterTest.java @@ -41,6 +41,12 @@ public class CodeStyleXmlImporterTest extends CodeStyleTestCase { assertEquals(true, settings.FORMATTER_TAGS_ENABLED); assertEquals(true, settings.FORMATTER_TAGS_ACCEPT_REGEXP); } + + public void testNewProjectSettings() throws SchemeImportException { + CodeStyleSettings settings= importSettings(); + assertEquals(140, settings.getDefaultRightMargin()); + assertEquals(true, settings.FORMATTER_TAGS_ENABLED); + } private CodeStyleSettings importSettings() throws SchemeImportException { final CodeStyleScheme targetScheme = new CodeStyleSchemeImpl("Test", false, null); From f49eb6eaadafa5a8c5d816c859188432df09c9f1 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 25 Oct 2017 16:28:34 +0300 Subject: [PATCH 25/46] AddJavadocIntention: fix exception when the intention invoked for package-info or module-info EA-109542 --- .../intention/impl/AddJavadocIntention.java | 44 +++++++++---------- .../com/intellij/ide/util/PackageUtil.java | 20 +++------ .../lang/java/JavaDocumentationProvider.java | 30 +++++++------ .../AddJavadocToModuleAndPackageTest.java | 32 ++++++++++++++ 4 files changed, 74 insertions(+), 52 deletions(-) create mode 100644 java/java-tests/testSrc/com/intellij/java/codeInsight/intention/AddJavadocToModuleAndPackageTest.java diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddJavadocIntention.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddJavadocIntention.java index 4f2e4fab8fe8..596a5dea0cd4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddJavadocIntention.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AddJavadocIntention.java @@ -1,45 +1,41 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInsight.intention.impl; import com.intellij.codeInsight.editorActions.FixDocCommentAction; import com.intellij.codeInsight.intention.BaseElementAtCaretIntentionAction; import com.intellij.codeInsight.intention.LowPriorityAction; +import com.intellij.ide.util.PackageUtil; +import com.intellij.lang.java.JavaDocumentationProvider; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; public class AddJavadocIntention extends BaseElementAtCaretIntentionAction implements LowPriorityAction { @Override public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException { - final PsiDocCommentOwner docCommentOwner = (PsiDocCommentOwner)element.getParent(); - FixDocCommentAction.generateOrFixComment(docCommentOwner, project, editor); + FixDocCommentAction.generateOrFixComment(element, project, editor); } @Override - public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) { - if (!(element instanceof PsiIdentifier)) { - return false; + public boolean isAvailable(@NotNull final Project project, final Editor editor, @NotNull PsiElement element) { + PsiElement targetElement = PsiTreeUtil.skipParentsOfType(element, PsiIdentifier.class, PsiJavaCodeReferenceElement.class, PsiJavaModuleReferenceElement.class); + if (targetElement instanceof PsiJavaDocumentedElement && + !(targetElement instanceof PsiTypeParameter) && + !(targetElement instanceof PsiAnonymousClass)) { + return ((PsiJavaDocumentedElement)targetElement).getDocComment() == null; } - final PsiElement parent = element.getParent(); - return parent instanceof PsiDocCommentOwner && - ((PsiDocCommentOwner)parent).getDocComment() == null && - !(parent instanceof PsiTypeParameter); + + if (targetElement instanceof PsiPackageStatement) { + PsiFile file = targetElement.getContainingFile(); + return PackageUtil.isPackageInfoFile(file) && JavaDocumentationProvider.getPackageInfoComment(file) == null; + } + else if (PackageUtil.isPackageInfoFile(targetElement)) { + return JavaDocumentationProvider.getPackageInfoComment(targetElement) == null; + } + return false; } @NotNull diff --git a/java/java-impl/src/com/intellij/ide/util/PackageUtil.java b/java/java-impl/src/com/intellij/ide/util/PackageUtil.java index 4d0081fe7461..fefa43c330bf 100644 --- a/java/java-impl/src/com/intellij/ide/util/PackageUtil.java +++ b/java/java-impl/src/com/intellij/ide/util/PackageUtil.java @@ -1,18 +1,4 @@ -/* - * 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide.util; import com.intellij.ide.IdeBundle; @@ -398,4 +384,8 @@ public class PackageUtil { public static PsiDirectory findOrCreateSubdirectory(@NotNull PsiDirectory directory, @NotNull String directoryName) { return CreateFileAction.findOrCreateSubdirectory(directory, directoryName); } + + public static boolean isPackageInfoFile(@Nullable PsiElement element) { + return element instanceof PsiJavaFile && PsiPackage.PACKAGE_INFO_FILE.equals(((PsiJavaFile)element).getName()); + } } diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java index 0caf4fa38b5d..81bddcbdf93d 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -1,6 +1,4 @@ -// Copyright 2000-2017 JetBrains s.r.o. -// Use of this source code is governed by the Apache 2.0 license that can be -// found in the LICENSE file. +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.lang.java; import com.intellij.codeInsight.CodeInsightBundle; @@ -12,6 +10,7 @@ import com.intellij.codeInsight.javadoc.JavaDocExternalFilter; import com.intellij.codeInsight.javadoc.JavaDocInfoGenerator; import com.intellij.codeInsight.javadoc.JavaDocInfoGeneratorFactory; import com.intellij.codeInsight.javadoc.JavaDocUtil; +import com.intellij.ide.util.PackageUtil; import com.intellij.lang.CodeDocumentationAwareCommenter; import com.intellij.lang.LangBundle; import com.intellij.lang.LanguageCommenters; @@ -392,18 +391,18 @@ public class JavaDocumentationProvider extends DocumentationProviderEx implement @Nullable @Override public Pair parseContext(@NotNull PsiElement startPoint) { - PsiElement docCommentOwner = PsiTreeUtil.findFirstParent(startPoint, e -> { - if (e instanceof PsiDocCommentOwner && !(e instanceof PsiTypeParameter) && !(e instanceof PsiAnonymousClass)) { - return true; + PsiElement current = startPoint; + while (current != null) { + if (current instanceof PsiJavaDocumentedElement && !(current instanceof PsiTypeParameter) && !(current instanceof PsiAnonymousClass)) { + PsiDocComment comment = ((PsiJavaDocumentedElement)current).getDocComment(); + return Pair.create(current instanceof PsiField ? ((PsiField)current).getModifierList() : current, comment); } - return false; - }); - if (docCommentOwner == null) return null; - PsiDocComment comment = ((PsiDocCommentOwner)docCommentOwner).getDocComment(); - if (docCommentOwner instanceof PsiField) { - docCommentOwner = ((PsiField)docCommentOwner).getModifierList(); + else if (PackageUtil.isPackageInfoFile(current)) { + return Pair.create(current, getPackageInfoComment(current)); + } + current = current.getParent(); } - return Pair.create(docCommentOwner, comment); + return null; } @Override @@ -730,6 +729,11 @@ public class JavaDocumentationProvider extends DocumentationProviderEx implement return signature; } + @Nullable + public static PsiDocComment getPackageInfoComment(@NotNull PsiElement packageInfoFile) { + return PsiTreeUtil.getChildOfType(packageInfoFile, PsiDocComment.class); + } + @Nullable public static List findUrlForClass(@NotNull PsiClass aClass) { String qName = aClass.getQualifiedName(); diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/intention/AddJavadocToModuleAndPackageTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/intention/AddJavadocToModuleAndPackageTest.java new file mode 100644 index 000000000000..d975f041c5ae --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/intention/AddJavadocToModuleAndPackageTest.java @@ -0,0 +1,32 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.java.codeInsight.intention; + +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; + +public class AddJavadocToModuleAndPackageTest extends LightCodeInsightFixtureTestCase { + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JAVA_9; + } + + public void testPackageInfo() { + myFixture.configureByText("package-info.java", "package org.some.awesome;"); + myFixture.launchAction(myFixture.findSingleIntention("Add Javadoc")); + myFixture.checkResult("/**\n" + + " * \n" + + " */\n" + + "package org.some.awesome;"); + } + + public void testModuleInfo() { + myFixture.configureByText("module-info.java", "module org.some.awesome{}"); + myFixture.launchAction(myFixture.findSingleIntention("Add Javadoc")); + myFixture.checkResult("/**\n" + + " * \n" + + " */\n" + + "module org.some.awesome{}"); + } +} From 4d0a58a4d8b881564bd4cf3b35c747e05614a42c Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Wed, 25 Oct 2017 16:50:26 +0300 Subject: [PATCH 26/46] Clean up legacy code style settings on import --- .../psi/impl/source/codeStyle/CodeStyleSchemeXmlImporter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeXmlImporter.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeXmlImporter.java index a275686505ab..c9238150eb96 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeXmlImporter.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeXmlImporter.java @@ -81,6 +81,7 @@ public class CodeStyleSchemeXmlImporter extends CodeStyleSettingsLoader implemen throws SchemeImportException { CodeStyleSettings newSettings = new CodeStyleSettings(); loadSettings(rootElement, newSettings); + newSettings.resetDeprecatedFields(); // Clean up if imported from legacy settings ((CodeStyleSchemeImpl)scheme).setCodeStyleSettings(newSettings); return scheme; } From 47a9d8a28409e9e1c3fb27c1f91652ac6ad5e3af Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 25 Oct 2017 15:08:37 +0300 Subject: [PATCH 27/46] move tree acceptor from TreeState to TreeUtil --- .../projectView/impl/AsyncProjectViewSupport.java | 7 +++---- .../newStructureView/StructureViewComponent.java | 2 +- .../com/intellij/ide/util/treeView/TreeState.java | 4 ++-- .../src/com/intellij/util/ui/tree/TreeUtil.java | 14 ++++++++++++++ 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AsyncProjectViewSupport.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AsyncProjectViewSupport.java index d7b756513cce..acce4cbf7212 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AsyncProjectViewSupport.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AsyncProjectViewSupport.java @@ -57,9 +57,8 @@ import java.util.Comparator; import java.util.List; import java.util.function.Predicate; -import static com.intellij.ide.util.treeView.TreeState.VISIT; import static com.intellij.ide.util.treeView.TreeState.expand; -import static com.intellij.util.ui.UIUtil.putClientProperty; +import static com.intellij.util.ui.tree.TreeUtil.setTreeAcceptor; import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; import static org.jetbrains.concurrency.Promises.collectResults; @@ -297,9 +296,9 @@ class AsyncProjectViewSupport { private static void setModel(@NotNull JTree tree, @NotNull AsyncTreeModel model) { tree.setModel(model); - putClientProperty(tree, VISIT, visitor -> model.accept(visitor, true)); + setTreeAcceptor(tree, model::accept); Disposer.register(model, () -> { - putClientProperty(tree, VISIT, null); + setTreeAcceptor(tree, null); tree.setModel(null); }); } diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java b/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java index deb81bda1602..35a6d6ba371d 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java +++ b/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java @@ -161,7 +161,7 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre myAsyncTreeModel = new AsyncTreeModel(myStructureTreeModel, true); myAsyncTreeModel.setRootImmediately(myStructureTreeModel.getRootImmediately()); myTree = new MyTree(myAsyncTreeModel); - UIUtil.putClientProperty(myTree, TreeState.VISIT, visitor -> myAsyncTreeModel.accept(visitor, true)); + TreeUtil.setTreeAcceptor(myTree, myAsyncTreeModel::accept); Disposer.register(this, () -> myTreeModelWrapper.dispose()); Disposer.register(this, myAsyncTreeModel); diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/TreeState.java b/platform/platform-api/src/com/intellij/ide/util/treeView/TreeState.java index b808ab358dc9..ec3d943fbf7e 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/TreeState.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/TreeState.java @@ -53,6 +53,7 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.Function; +import static com.intellij.util.ui.tree.TreeUtil.getTreeAcceptor; import static java.util.stream.Collectors.toList; import static org.jetbrains.concurrency.Promises.collectResults; @@ -66,7 +67,6 @@ public class TreeState implements JDOMExternalizable { private static final Logger LOG = Logger.getInstance(TreeState.class); public static final Key> CALLBACK = Key.create("Callback"); - public static final Key>> VISIT = Key.create("TreeVisit"); private static final Key> EXPANDING = Key.create("TreeExpanding"); private static final String EXPAND_TAG = "expand"; @@ -481,7 +481,7 @@ public class TreeState implements JDOMExternalizable { } private boolean visit(@NotNull JTree tree) { - Function> acceptor = UIUtil.getClientProperty(tree, VISIT); + Function> acceptor = getTreeAcceptor(tree); if (acceptor == null) return false; expand(tree, promise -> expand(acceptor, tree).processed(expanded -> { diff --git a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java index b2d2c6ddf0fa..5d607542cc1f 100644 --- a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java +++ b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java @@ -22,10 +22,12 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Key; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.ScrollingUtil; import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.awt.RelativePoint; +import com.intellij.ui.tree.TreeVisitor; import com.intellij.ui.treeStructure.Tree; import com.intellij.util.Range; import com.intellij.util.containers.JBIterable; @@ -33,6 +35,7 @@ import com.intellij.util.containers.JBTreeTraverser; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.Promise; import javax.swing.*; import javax.swing.plaf.basic.BasicTreeUI; @@ -42,6 +45,7 @@ import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.*; import java.util.List; +import java.util.function.Function; import static com.intellij.openapi.wm.IdeFocusManager.getGlobalInstance; @@ -49,9 +53,19 @@ public final class TreeUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.util.ui.tree.TreeUtil"); private static final String TREE_UTIL_SCROLL_TIME_STAMP = "TreeUtil.scrollTimeStamp"; private static final JBIterable NUMBERS = JBIterable.generate(0, i -> i + 1); + private static final Key>> TREE_ACCEPTOR = Key.create("TreeAcceptor"); private TreeUtil() {} + @Nullable + public static Function> getTreeAcceptor(@NotNull JTree tree) { + return UIUtil.getClientProperty(tree, TREE_ACCEPTOR); + } + + public static void setTreeAcceptor(@NotNull JTree tree, @Nullable Function> acceptor) { + UIUtil.putClientProperty(tree, TREE_ACCEPTOR, acceptor); + } + @NotNull public static JBTreeTraverser treePathTraverser(@NotNull JTree tree) { TreeModel model = tree.getModel(); From ec269566c19e36bb956ca68d67d6a95a92f5c1d5 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 25 Oct 2017 16:43:49 +0300 Subject: [PATCH 28/46] fix package view test and introduce utility methods to expand nodes --- .../PackagesTreeStructureTest.java | 5 +- .../com/intellij/util/ui/tree/TreeUtil.java | 74 +++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java b/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java index c1c469a371fa..97d40af133fb 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java +++ b/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java @@ -28,9 +28,12 @@ import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.TestSourceBasedTestCase; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.concurrency.AsyncPromise; import javax.swing.*; +import java.awt.*; import java.io.IOException; +import java.util.concurrent.atomic.AtomicBoolean; public class PackagesTreeStructureTest extends TestSourceBasedTestCase { public void testPackageView() { @@ -218,7 +221,7 @@ public class PackagesTreeStructureTest extends TestSourceBasedTestCase { ((AbstractProjectTreeStructure) packageViewPane.getTreeStructure()).setProviders(new ResourceBundleGrouper(myProject)); packageViewPane.updateFromRoot(true); JTree tree = packageViewPane.getTree(); - TreeUtil.expand(tree, levels); + PlatformTestUtil.waitForPromise(TreeUtil.promiseExpand(tree, levels - 1)); // -1 because root node is not visible PlatformTestUtil.assertTreeEqual(tree, expected); BaseProjectViewTestCase.checkContainsMethod(packageViewPane.getTreeStructure().getRootElement(), packageViewPane.getTreeStructure()); Disposer.dispose(packageViewPane); diff --git a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java index 5d607542cc1f..5b4acaf3a973 100644 --- a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java +++ b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java @@ -35,6 +35,7 @@ import com.intellij.util.containers.JBTreeTraverser; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.AsyncPromise; import org.jetbrains.concurrency.Promise; import javax.swing.*; @@ -804,6 +805,34 @@ public final class TreeUtil { while (true); } + /** + * Promises to expands all nodes in the specified tree. + * + * @param tree a tree, which nodes should be expanded + */ + public static Promise promiseExpandAll(@NotNull JTree tree) { + AsyncPromise promise = new AsyncPromise<>(); + expandAll(tree, () -> promise.setResult(tree)); + return promise; + } + + /** + * Expands all nodes in the specified tree and runs the specified task on done. + * + * @param tree a tree, which nodes should be expanded + * @param onDone a task to run after expanding nodes + */ + public static void expandAll(@NotNull JTree tree, Runnable onDone) { + Function> acceptor = getTreeAcceptor(tree); + if (acceptor != null) { + expand(tree, acceptor, Integer.MAX_VALUE, onDone); + } + else { + expandAll(tree); + if (onDone != null) onDone.run(); + } + } + /** * Expands n levels of the tree counting from the root * @param tree to expand nodes of @@ -829,6 +858,51 @@ public final class TreeUtil { return isReady; } + /** + * Promises to expands some nodes in the specified tree. + * + * @param tree a tree, which nodes should be expanded + * @param depth a depth from visible root + */ + public static Promise promiseExpand(@NotNull JTree tree, int depth) { + AsyncPromise promise = new AsyncPromise<>(); + expand(tree, depth, () -> promise.setResult(tree)); + return promise; + } + + /** + * Expands some nodes in the specified tree and runs the specified task on done. + * + * @param tree a tree, which nodes should be expanded + * @param depth a depth from visible root + * @param onDone a task to run after expanding nodes + */ + public static void expand(@NotNull JTree tree, int depth, Runnable onDone) { + if (depth < Integer.MAX_VALUE && !tree.isRootVisible()) depth++; + Function> acceptor = depth <= 0 ? null : getTreeAcceptor(tree); + if (acceptor != null) { + expand(tree, acceptor, depth, onDone); + } + else { + if (depth > 0) expand(tree, depth); + if (onDone != null) onDone.run(); + } + } + + private static void expand(@NotNull JTree tree, @NotNull Function> acceptor, int depth, Runnable onDone) { + Promise promise = acceptor.apply(new TreeVisitor() { + @NotNull + @Override + public Action visit(@NotNull TreePath path) { + int count = path.getPathCount(); + if (count > depth) return Action.SKIP_SIBLINGS; + tree.expandPath(path); + return Action.CONTINUE; + } + }); + if (onDone != null) promise.processed(ignored -> onDone.run()); + } + @NotNull public static ActionCallback selectInTree(DefaultMutableTreeNode node, boolean requestFocus, @NotNull JTree tree) { return selectInTree(node, requestFocus, tree, true); From 86aa6e104c14d2f8c4b82618ba1ce12a4659908b Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 25 Oct 2017 16:44:46 +0300 Subject: [PATCH 29/46] do not warn about a loading node in visitor --- .../src/com/intellij/ui/tree/AbstractTreeNodeVisitor.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ui/tree/AbstractTreeNodeVisitor.java b/platform/platform-impl/src/com/intellij/ui/tree/AbstractTreeNodeVisitor.java index 168f56134837..c753c53562ac 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/AbstractTreeNodeVisitor.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/AbstractTreeNodeVisitor.java @@ -55,10 +55,16 @@ public abstract class AbstractTreeNodeVisitor implements TreeVisitor { if (object instanceof AbstractTreeNode) { return visit(path, (AbstractTreeNode)object, element); } + else if (object instanceof String) { + LOG.debug("ignore children: ", object); + } else { LOG.warn(object == null ? "no object" : "unexpected object " + object.getClass()); } } + else if (component instanceof String) { + LOG.debug("ignore children: ", component); + } else { LOG.warn(component == null ? "no component" : "unexpected component " + component.getClass()); } From 4f279019ef1351cca076475c7d498cdc89751bd2 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 25 Oct 2017 16:47:46 +0300 Subject: [PATCH 30/46] progress indicators are indeterminate by default more indicators fixed --- .../intellij/codeInsight/editorActions/JoinLinesHandler.java | 1 + platform/platform-api/src/com/intellij/util/net/NetUtils.java | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java index 084d900fef95..575a6dd7a12e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java @@ -100,6 +100,7 @@ public class JoinLinesHandler extends EditorActionHandler { ((ApplicationImpl)ApplicationManager.getApplication()).runWriteActionWithProgressInDispatchThread( "Join Lines", project, null, IdeBundle.message("action.stop"), indicator -> { + indicator.setIndeterminate(false); Ref caretRestoreOffset = new Ref<>(-1); CodeEditUtil.setNodeReformatStrategy(node -> node.getTextRange().getStartOffset() >= startReformatOffset); try { diff --git a/platform/platform-api/src/com/intellij/util/net/NetUtils.java b/platform/platform-api/src/com/intellij/util/net/NetUtils.java index db2819c8199f..ba750fcbc490 100644 --- a/platform/platform-api/src/com/intellij/util/net/NetUtils.java +++ b/platform/platform-api/src/com/intellij/util/net/NetUtils.java @@ -184,9 +184,7 @@ public class NetUtils { int expectedContentLength) throws IOException, ProcessCanceledException { if (indicator != null) { indicator.checkCanceled(); - if (expectedContentLength < 0) { - indicator.setIndeterminate(true); - } + indicator.setIndeterminate(expectedContentLength < 0); } CountingGZIPInputStream gzipStream = ObjectUtils.tryCast(inputStream, CountingGZIPInputStream.class); final byte[] buffer = new byte[8 * 1024]; From 0d3852d8d11061f3182e84ac3700f5a7bb02e70d Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 25 Oct 2017 16:50:50 +0300 Subject: [PATCH 31/46] progress indicators are indeterminate by default --- .../progress/util/AbstractProgressIndicatorBase.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) 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 3512161199c8..9418a8feee0f 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 @@ -179,13 +179,16 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements @Override public void setFraction(final double fraction) { + LOG.assertTrue(!isIndeterminate(), "This progress indicator is indeterminate. Please call setIndeterminate(false) first."); myFraction = fraction; } @Override public synchronized void pushState() { getTextStack().push(myText); - getFractionStack().add(myFraction); + if (!isIndeterminate()) { + getFractionStack().add(myFraction); + } getText2Stack().push(myText2); } @@ -193,11 +196,14 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements public synchronized void popState() { LOG.assertTrue(!myTextStack.isEmpty()); String oldText = myTextStack.pop(); - double oldFraction = myFractionStack.remove(myFractionStack.size() - 1); String oldText2 = myText2Stack.pop(); setText(oldText); - setFraction(oldFraction); setText2(oldText2); + + if (!isIndeterminate()) { + double oldFraction = myFractionStack.remove(myFractionStack.size() - 1); + setFraction(oldFraction); + } } @Override From f4a81201c74fe151f16ca36c5ad6e2c021d24ae0 Mon Sep 17 00:00:00 2001 From: "Irina.Chernushina" Date: Wed, 25 Oct 2017 15:30:56 +0200 Subject: [PATCH 32/46] rng parser: for cache, value reference should be soft - also, if there is a key with empty soft reference, putIfAbsent does not work => always rewrite the value in cache WEB-29413 OOM while indexing vue project 'cropchat' --- .../org/intellij/plugins/relaxNG/validation/RngParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/RngParser.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/RngParser.java index 69c7ad4b3982..bf225177c443 100644 --- a/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/RngParser.java +++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/RngParser.java @@ -86,7 +86,7 @@ public class RngParser { } }; - private static final ConcurrentMap ourCache = ContainerUtil.createConcurrentSoftMap(); + private static final ConcurrentMap ourCache = ContainerUtil.createConcurrentSoftValueMap(); private static DatatypeLibraryFactory createXsdDatatypeFactory() { try { @@ -121,7 +121,7 @@ public class RngParser { pattern = parsePattern(descriptorFile, eh, false); } if (pattern != null) { - DPattern oldPattern = ourCache.putIfAbsent(url, pattern); + DPattern oldPattern = ourCache.put(url, pattern); if (oldPattern != null) { return oldPattern; } From 28185c8e7b897c18498b013110f596335e3e13b4 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 25 Oct 2017 12:32:07 +0200 Subject: [PATCH 33/46] extract RunConfigurationListManagerHelper to simplify RunManagerImpl --- .../impl/RunConfigurationListManagerHelper.kt | 186 ++++++++++++++++++ .../intellij/execution/impl/RunManagerImpl.kt | 180 ++--------------- 2 files changed, 203 insertions(+), 163 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationListManagerHelper.kt diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationListManagerHelper.kt b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationListManagerHelper.kt new file mode 100644 index 000000000000..cad331cc5c8f --- /dev/null +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationListManagerHelper.kt @@ -0,0 +1,186 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.execution.impl + +import com.intellij.execution.RunnerAndConfigurationSettings +import com.intellij.execution.compound.CompoundRunConfiguration +import com.intellij.execution.configurations.RunConfiguration +import com.intellij.execution.configurations.UnknownConfigurationType +import com.intellij.openapi.util.text.NaturalComparator +import com.intellij.util.SmartList +import com.intellij.util.containers.ContainerUtil +import com.intellij.util.containers.ObjectIntHashMap +import java.util.* + +internal class RunConfigurationListManagerHelper(val manager: RunManagerImpl) { + // template configurations are not included here + val idToSettings = LinkedHashMap() + + private val customOrder = ObjectIntHashMap() + + private var isCustomOrderApplied = true + set(value) { + if (field != value) { + field = value + if (!value) { + immutableSortedSettingsList = null + } + } + } + + @Volatile + var immutableSortedSettingsList: List? = emptyList() + + fun setOrder(comparator: Comparator?) { + val sorted = idToSettings.values.filterTo(ArrayList(idToSettings.size)) { it.type !is UnknownConfigurationType } + if (comparator != null) { + sorted.sortWith(comparator) + } + customOrder.clear() + customOrder.ensureCapacity(sorted.size) + sorted.mapIndexed { index, settings -> customOrder.put(settings.uniqueID, index) } + immutableSortedSettingsList = null + isCustomOrderApplied = false + } + + fun requestSort() { + if (customOrder.isEmpty) { + sortAlphabetically() + } + else { + isCustomOrderApplied = false + } + immutableSortedSettingsList = null + manager.allSettings + } + + fun loadOrder(order: ArrayList) { + customOrder.clear() + customOrder.ensureCapacity(order.size) + order.mapIndexed { index, id -> customOrder.put(id, index) } + + // DeprecatedProjectRunConfigurationManager will not call requestSort if no shared configurations + requestSort() + } + + private fun sortAlphabetically() { + if (idToSettings.isEmpty()) { + return + } + + val list = idToSettings.values.sortedWith(Comparator { o1, o2 -> + val temporary1 = o1.isTemporary + val temporary2 = o2.isTemporary + when { + temporary1 == temporary2 -> o1.uniqueID.compareTo(o2.uniqueID) + temporary1 -> 1 + else -> -1 + } + }) + idToSettings.clear() + for (settings in list) { + idToSettings.put(settings.uniqueID, settings) + } + } + + fun buildImmutableSortedSettingsList(): List { + immutableSortedSettingsList?.let { + return it + } + + if (idToSettings.isEmpty()) { + immutableSortedSettingsList = emptyList() + return immutableSortedSettingsList!! + } + + // IDEA-63663 Sort run configurations alphabetically if clean checkout + if (!isCustomOrderApplied && !customOrder.isEmpty) { + val list = idToSettings.values.toTypedArray() + val folderNames = SmartList() + for (settings in list) { + val folderName = settings.folderName + if (folderName != null && !folderNames.contains(folderName)) { + folderNames.add(folderName) + } + } + + folderNames.sortWith(NaturalComparator.INSTANCE) + folderNames.add(null) + + list.sortWith(Comparator { o1, o2 -> + if (o1.folderName != o2.folderName) { + val i1 = folderNames.indexOf(o1.folderName) + val i2 = folderNames.indexOf(o2.folderName) + if (i1 != i2) { + return@Comparator i1 - i2 + } + } + + val temporary1 = o1.isTemporary + val temporary2 = o2.isTemporary + when { + temporary1 == temporary2 -> { + val index1 = customOrder.get(o1.uniqueID) + val index2 = customOrder.get(o2.uniqueID) + if (index1 == -1 && index2 == -1) { + o1.name.compareTo(o2.name) + } + else { + index1 - index2 + } + } + temporary1 -> 1 + else -> -1 + } + }) + + isCustomOrderApplied = true + idToSettings.clear() + for (settings in list) { + idToSettings.put(settings.uniqueID, settings) + } + } + + val result = Collections.unmodifiableList(idToSettings.values.toList()) + immutableSortedSettingsList = result + return result + } + + fun afterMakeStable() { + immutableSortedSettingsList = null + if (!customOrder.isEmpty) { + isCustomOrderApplied = false + } + } + + fun checkIfDependenciesAreStable(configuration: RunConfiguration, list: List) { + for (runTask in configuration.beforeRunTasks) { + val runTaskSettings = (runTask as? RunConfigurationBeforeRunProvider.RunConfigurableBeforeRunTask)?.settings + + if (runTaskSettings?.isTemporary == true) { + manager.makeStable(runTaskSettings) + checkIfDependenciesAreStable(runTaskSettings.configuration, list) + } + } + + if (configuration is CompoundRunConfiguration) { + val children = configuration.getConfigurationsWithTargets(manager) + for (otherSettings in list) { + if (!otherSettings.isTemporary) { + continue + } + + val otherConfiguration = otherSettings.configuration + if (otherConfiguration === configuration) { + continue + } + + if (ContainerUtil.containsIdentity(children.keys, otherConfiguration)) { + if (otherSettings.isTemporary) { + manager.makeStable(otherSettings) + checkIfDependenciesAreStable(otherConfiguration, list) + } + } + } + } + } +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt index 41fd20ff996e..5dcdd6dd5f82 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt @@ -4,7 +4,6 @@ package com.intellij.execution.impl import com.intellij.ProjectTopics import com.intellij.configurationStore.* import com.intellij.execution.* -import com.intellij.execution.compound.CompoundRunConfiguration import com.intellij.execution.configurations.* import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.execution.runners.ExecutionUtil @@ -26,7 +25,6 @@ import com.intellij.openapi.roots.ModuleRootListener import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.UnknownFeaturesCollector import com.intellij.openapi.util.Key import com.intellij.openapi.util.registry.Registry -import com.intellij.openapi.util.text.NaturalComparator import com.intellij.util.IconUtil import com.intellij.util.SmartList import com.intellij.util.containers.* @@ -85,9 +83,13 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi private val idToType = LinkedHashMap() + @Suppress("LeakingThis") + private val listManager = RunConfigurationListManagerHelper(this) + private val templateIdToConfiguration = THashMap() // template configurations are not included here - private val idToSettings = LinkedHashMap() + private val idToSettings: LinkedHashMap + get() = listManager.idToSettings // When readExternal not all configuration may be loaded, so we need to remember the selected configuration // so that when it is eventually loaded, we can mark is as a selected. @@ -96,17 +98,6 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi private val iconCache = TimedIconCache() private val _config by lazy { RunManagerConfig(PropertiesComponent.getInstance(project)) } - private var isCustomOrderApplied = true - set(value) { - if (field != value) { - field = value - if (!value) { - immutableSortedSettingsList = null - } - } - } - - private val customOrder = ObjectIntHashMap() private val recentlyUsedTemporaries = ArrayList() private val workspaceSchemeManagerProvider = SchemeManagerIprProvider("configuration") @@ -247,7 +238,7 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi val newId = settings.uniqueID var existingId: String? = null lock.write { - immutableSortedSettingsList = null + listManager.immutableSortedSettingsList = null // https://youtrack.jetbrains.com/issue/IDEA-112821 // we should check by instance, not by id (todo is it still relevant?) @@ -346,15 +337,7 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi // yes, on hot reload, because our DeprecatedProjectRunConfigurationManager doesn't use SchemeManager and change of some RC file leads to reload of all configurations fun setOrder(comparator: Comparator?) { lock.write { - val sorted = idToSettings.values.filterTo(ArrayList(idToSettings.size)) { it.type !is UnknownConfigurationType } - if (comparator != null) { - sorted.sortWith(comparator) - } - customOrder.clear() - customOrder.ensureCapacity(sorted.size) - sorted.mapIndexed { index, settings -> customOrder.put(settings.uniqueID, index) } - immutableSortedSettingsList = null - isCustomOrderApplied = false + listManager.setOrder(comparator) } } @@ -369,119 +352,30 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi eventPublisher.runConfigurationSelected() } - @Volatile - private var immutableSortedSettingsList: List? = emptyList() - fun requestSort() { lock.write { - if (customOrder.isEmpty) { - sortAlphabetically() - } - else { - isCustomOrderApplied = false - } - immutableSortedSettingsList = null - allSettings + listManager.requestSort() } } override val allSettings: List get() { - immutableSortedSettingsList?.let { + listManager.immutableSortedSettingsList?.let { return it } lock.write { - immutableSortedSettingsList?.let { - return it - } - - if (idToSettings.isEmpty()) { - immutableSortedSettingsList = emptyList() - return immutableSortedSettingsList!! - } - - // IDEA-63663 Sort run configurations alphabetically if clean checkout - if (!isCustomOrderApplied && !customOrder.isEmpty) { - val list = idToSettings.values.toTypedArray() - val folderNames = SmartList() - for (settings in list) { - val folderName = settings.folderName - if (folderName != null && !folderNames.contains(folderName)) { - folderNames.add(folderName) - } - } - - folderNames.sortWith(NaturalComparator.INSTANCE) - folderNames.add(null) - - list.sortWith(Comparator { o1, o2 -> - if (o1.folderName != o2.folderName) { - val i1 = folderNames.indexOf(o1.folderName) - val i2 = folderNames.indexOf(o2.folderName) - if (i1 != i2) { - return@Comparator i1 - i2 - } - } - - val temporary1 = o1.isTemporary - val temporary2 = o2.isTemporary - when { - temporary1 == temporary2 -> { - val index1 = customOrder.get(o1.uniqueID) - val index2 = customOrder.get(o2.uniqueID) - if (index1 == -1 && index2 == -1) { - o1.name.compareTo(o2.name) - } - else { - index1 - index2 - } - } - temporary1 -> 1 - else -> -1 - } - }) - - isCustomOrderApplied = true - idToSettings.clear() - for (settings in list) { - idToSettings.put(settings.uniqueID, settings) - } - } - - val result = Collections.unmodifiableList(idToSettings.values.toList()) - immutableSortedSettingsList = result - return result + return listManager.buildImmutableSortedSettingsList() } } - private fun sortAlphabetically() { - if (idToSettings.isEmpty()) { - return - } - - val list = idToSettings.values.sortedWith(Comparator { o1, o2 -> - val temporary1 = o1.isTemporary - val temporary2 = o2.isTemporary - when { - temporary1 == temporary2 -> o1.uniqueID.compareTo(o2.uniqueID) - temporary1 -> 1 - else -> -1 - } - }) - idToSettings.clear() - for (settings in list) { - idToSettings.put(settings.uniqueID, settings) - } - } - override fun getState(): Element { if (!isFirstLoadState.get()) { lock.read { val list = idToSettings.values.toList() for (settings in list) { if (settings.type !is UnknownConfigurationType) { - checkIfDependenciesAreStable(settings.configuration, list) + listManager.checkIfDependenciesAreStable(settings.configuration, list) } } } @@ -669,12 +563,7 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi com.intellij.openapi.util.JDOMExternalizableStringList.readList(order, parentNode) lock.write { - customOrder.clear() - customOrder.ensureCapacity(order.size) - order.mapIndexed { index, id -> customOrder.put(id, index) } - - // DeprecatedProjectRunConfigurationManager will not call requestSort if no shared configurations - requestSort() + listManager.loadOrder(order) recentlyUsedTemporaries.clear() val recentNode = parentNode.getChild(RECENT) @@ -688,7 +577,7 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi } } } - immutableSortedSettingsList = null + listManager.immutableSortedSettingsList = null selectedConfigurationId = parentNode.getAttributeValue(SELECTED_ATTR) } @@ -747,7 +636,7 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi private fun clear(allConfigurations: Boolean) { val removedConfigurations = lock.write { - immutableSortedSettingsList = null + listManager.immutableSortedSettingsList = null val configurations = if (allConfigurations) { val configurations = idToSettings.values.toList() @@ -880,10 +769,7 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi private fun doMakeStable(settings: RunnerAndConfigurationSettings) { lock.write { recentlyUsedTemporaries.remove(settings) - immutableSortedSettingsList = null - if (!customOrder.isEmpty) { - isCustomOrderApplied = false - } + listManager.afterMakeStable() } } @@ -1044,7 +930,7 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi if (value && settings.isTemporary) { doMakeStable(settings) } - (settings as RunnerAndConfigurationSettingsImpl).isShared = value + settings.isShared = value fireRunConfigurationChanged(settings) } @@ -1092,38 +978,6 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi fireBeforeRunTasksUpdated() } - private fun checkIfDependenciesAreStable(configuration: RunConfiguration, list: List) { - for (runTask in configuration.beforeRunTasks) { - val runTaskSettings = (runTask as? RunConfigurationBeforeRunProvider.RunConfigurableBeforeRunTask)?.settings - - if (runTaskSettings?.isTemporary == true) { - makeStable(runTaskSettings) - checkIfDependenciesAreStable(runTaskSettings.configuration, list) - } - } - - if (configuration is CompoundRunConfiguration) { - val children = configuration.getConfigurationsWithTargets(this) - for (otherSettings in list) { - if (!otherSettings.isTemporary) { - continue - } - - val otherConfiguration = otherSettings.configuration - if (otherConfiguration === configuration) { - continue - } - - if (ContainerUtil.containsIdentity(children.keys, otherConfiguration)) { - if (otherSettings.isTemporary) { - makeStable(otherSettings) - checkIfDependenciesAreStable(otherConfiguration, list) - } - } - } - } - } - fun fireBeginUpdate() { eventPublisher.beginUpdate() } @@ -1160,7 +1014,7 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi val removed = SmartList() var selectedConfigurationWasRemoved = false lock.write { - immutableSortedSettingsList = null + listManager.immutableSortedSettingsList = null val iterator = idToSettings.values.iterator() for (settings in iterator) { From dbba10576789d356376614542ef9cf27ec40c8cf Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 25 Oct 2017 15:51:33 +0200 Subject: [PATCH 34/46] extract BeforeRunTaskHelper to simplify RunManagerImpl --- .../execution/impl/BeforeRunTaskHelper.kt | 53 +++++++++++++++++++ .../intellij/execution/impl/RunManagerImpl.kt | 48 +---------------- 2 files changed, 54 insertions(+), 47 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/execution/impl/BeforeRunTaskHelper.kt diff --git a/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunTaskHelper.kt b/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunTaskHelper.kt new file mode 100644 index 000000000000..17f78276a068 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/execution/impl/BeforeRunTaskHelper.kt @@ -0,0 +1,53 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.execution.impl + +import com.intellij.execution.BeforeRunTask +import com.intellij.execution.BeforeRunTaskProvider +import com.intellij.execution.configurations.RunConfiguration +import com.intellij.openapi.extensions.Extensions +import com.intellij.util.SmartList +import com.intellij.util.containers.filterSmartMutable +import com.intellij.util.containers.mapSmartSet +import com.intellij.util.containers.nullize + +internal fun getEffectiveBeforeRunTaskList(ownTasks: List>, templateTasks: List>, ownIsOnlyEnabled: Boolean, isDisableTemplateTasks: Boolean): MutableList> { + val idToSet = ownTasks.mapSmartSet { it.providerId } + val result = ownTasks.filterSmartMutable { !ownIsOnlyEnabled || it.isEnabled } + var i = 0 + for (templateTask in templateTasks) { + if (templateTask.isEnabled && !idToSet.contains(templateTask.providerId)) { + val effectiveTemplateTask = if (isDisableTemplateTasks) { + val clone = templateTask.clone() + clone.isEnabled = false + clone + } + else { + templateTask + } + result.add(i, effectiveTemplateTask) + i++ + } + } + return result +} + +internal fun getTemplateBeforeRunTasks(templateConfiguration: RunConfiguration): List> { + return templateConfiguration.beforeRunTasks.nullize() ?: getHardcodedBeforeRunTasks(templateConfiguration) +} + +internal fun getHardcodedBeforeRunTasks(configuration: RunConfiguration): List> { + var result: MutableList>? = null + for (provider in Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, configuration.project)) { + val task = provider.createTask(configuration) ?: continue + if (task.isEnabled) { + configuration.factory.configureBeforeRunTaskDefaults(provider.id, task) + if (task.isEnabled) { + if (result == null) { + result = SmartList>() + } + result.add(task) + } + } + } + return result.orEmpty() +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt index 5dcdd6dd5f82..5cccd76eaf5d 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.kt @@ -15,7 +15,6 @@ import com.intellij.openapi.components.Storage import com.intellij.openapi.components.StoragePathMacros import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.diagnostic.runAndLogException -import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.options.SchemeManager import com.intellij.openapi.options.SchemeManagerFactory import com.intellij.openapi.project.IndexNotReadyException @@ -706,7 +705,7 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi for (methodElement in child.getChildren(OPTION)) { val key = methodElement.getAttributeValue(NAME_ATTR) val provider = stringIdToBeforeRunProvider.getOrPut(key) { UnknownBeforeRunTaskProvider(key) } - val beforeRunTask = (if (provider is RunConfigurationBeforeRunProvider) provider.createTask(settings.configuration, this) else provider.createTask(settings.configuration)) ?: continue + val beforeRunTask = provider.createTask(settings.configuration) ?: continue if (beforeRunTask is PersistentStateComponent<*>) { // for PersistentStateComponent we don't write default value for enabled, so, set it to true explicitly beforeRunTask.isEnabled = true @@ -877,51 +876,6 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi return getEffectiveBeforeRunTaskList(ownTasks, templateTasks, ownIsOnlyEnabled, isDisableTemplateTasks = isDisableTemplateTasks) } - private fun getEffectiveBeforeRunTaskList(ownTasks: List>, - templateTasks: List>, - ownIsOnlyEnabled: Boolean, - isDisableTemplateTasks: Boolean): MutableList> { - val idToSet = ownTasks.mapSmartSet { it.providerId } - val result = ownTasks.filterSmartMutable { !ownIsOnlyEnabled || it.isEnabled } - var i = 0 - for (templateTask in templateTasks) { - if (templateTask.isEnabled && !idToSet.contains(templateTask.providerId)) { - val effectiveTemplateTask = if (isDisableTemplateTasks) { - val clone = templateTask.clone() - clone.isEnabled = false - clone - } - else { - templateTask - } - result.add(i, effectiveTemplateTask) - i++ - } - } - return result - } - - private fun getTemplateBeforeRunTasks(templateConfiguration: RunConfiguration): List> { - return templateConfiguration.beforeRunTasks.nullize() ?: getHardcodedBeforeRunTasks(templateConfiguration) - } - - private fun getHardcodedBeforeRunTasks(configuration: RunConfiguration): List> { - var result: MutableList>? = null - for (provider in Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, project)) { - val task = provider.createTask(configuration) ?: continue - if (task.isEnabled) { - configuration.factory.configureBeforeRunTaskDefaults(provider.id, task) - if (task.isEnabled) { - if (result == null) { - result = SmartList>() - } - result.add(task) - } - } - } - return result.orEmpty() - } - fun shareConfiguration(settings: RunnerAndConfigurationSettings, value: Boolean) { if (settings.isShared == value) { return From 0402d94bcf7741d2b11c0b68c47b2c118f953b13 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 25 Oct 2017 15:52:32 +0200 Subject: [PATCH 35/46] IDEA-181176 "before run task" is not loaded --- .../impl/RunConfigurationBeforeRunProvider.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java index 8a59b34ae43e..8d8323823af7 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java @@ -90,17 +90,6 @@ extends BeforeRunTaskProvider configurations = runManager.getAllSettings(); - if (configurations.isEmpty() || (configurations.size() == 1 && configurations.get(0).getConfiguration() == runConfiguration)) { - return null; - } - } return new RunConfigurableBeforeRunTask(); } From 0912e4bec9f670f2d4a2a272e3407d53461eafd1 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 25 Oct 2017 17:06:57 +0300 Subject: [PATCH 36/46] add logging to investigate EA-1619327 --- .../com/intellij/ide/util/treeView/AbstractTreeUi.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index bc239aa4cfe2..85e6cbc2f50d 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -3636,7 +3636,14 @@ public class AbstractTreeUi { if (descriptor.getChildrenSortingStamp() >= getComparatorStamp() && !forceSort) return; if (!children.isEmpty()) { - getBuilder().sortChildren(myNodeComparator, node, (ArrayList)children); + try { + getBuilder().sortChildren(myNodeComparator, node, (ArrayList)children); + } + catch (IllegalArgumentException exception) { + StringBuilder sb = new StringBuilder("cannot sort children"); + children.forEach(child -> sb.append('\n').append(child)); + throw new IllegalArgumentException(sb.toString(), exception); + } } if (updateStamp) { From dcc06e0e5c73ccb12b3dad0eac2842a33f42d71b Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 25 Oct 2017 17:28:46 +0300 Subject: [PATCH 37/46] inspection view: use notNull with factory since descriptor can be one of actual or resolved EA-108592 --- .../ui/DefaultInspectionToolPresentation.java | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java index 93ed1ce29b22..132a32429f11 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInspection.ui; import com.intellij.codeHighlighting.HighlightDisplayLevel; @@ -176,7 +162,7 @@ public class DefaultInspectionToolPresentation implements InspectionToolPresenta @Override public void exclude(@NotNull CommonProblemDescriptor descriptor) { - RefEntity entity = ObjectUtils.notNull(myProblemElements.getKeyFor(descriptor), myResolvedElements.getKeyFor(descriptor)); + RefEntity entity = ObjectUtils.notNull(myProblemElements.getKeyFor(descriptor), () -> myResolvedElements.getKeyFor(descriptor)); myExcludedElements.put(entity, descriptor); } From 4a0be0bf36c4233c4595d482273fe32a6c9cabfd Mon Sep 17 00:00:00 2001 From: Ivan Bessonov Date: Wed, 25 Oct 2017 17:31:22 +0300 Subject: [PATCH 38/46] IDEA-CR-25932 bintray repositories indexing - ability to detect repository owner by url subdomain --- .../idea/maven/indices/MavenIndex.java | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java index 5472b75991cf..bf76439e53fb 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java @@ -17,7 +17,6 @@ package org.jetbrains.idea.maven.indices; import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.util.CachedValueImpl; @@ -40,8 +39,12 @@ import org.jetbrains.idea.maven.utils.MavenProcessCanceledException; import org.jetbrains.idea.maven.utils.MavenProgressIndicator; import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; import java.util.*; +import static com.intellij.openapi.util.text.StringUtil.*; + public class MavenIndex { private static final String CURRENT_VERSION = "4"; @@ -130,7 +133,7 @@ public class MavenIndex { String myRepositoryIdsStr = props.getProperty(ID_KEY); if (myRepositoryIdsStr != null) { - myRegisteredRepositoryIds.addAll(StringUtil.split(myRepositoryIdsStr, ",")); + myRegisteredRepositoryIds.addAll(split(myRepositoryIdsStr, ",")); } myRepositoryPathOrUrl = normalizePathOrUrl(props.getProperty(PATH_OR_URL_KEY)); @@ -150,13 +153,26 @@ public class MavenIndex { } private static NotNexusIndexer initNotNexusIndexer(Kind kind, String repositoryPathOrUrl) { - if (kind == Kind.REMOTE && repositoryPathOrUrl.contains("dl.bintray.com/")) { - List subjectAndRepo = - StringUtil.split(repositoryPathOrUrl.substring(repositoryPathOrUrl.indexOf("dl.bintray.com/") + "dl.bintray.com/".length()), "/"); - if (!subjectAndRepo.isEmpty()) { - String subject = subjectAndRepo.get(0); - String repo = subjectAndRepo.size() > 1 ? subjectAndRepo.get(1) : null; - return new BintrayIndexer(subject, repo); + if (kind == Kind.REMOTE) { + try { + URL url = new URL(repositoryPathOrUrl); + + String host = url.getHost(); + if (host != null) { + List path = split(trimStart(url.getPath(), "/"), "/"); + if (host.equals("dl.bintray.com")) { + if (path.size() > 1) { + return new BintrayIndexer(path.get(0), path.get(1)); + } + } + else if (host.endsWith(".bintray.com")) { + if (!path.isEmpty()) { + return new BintrayIndexer(trimEnd(host, ".bintray.com"), path.get(0)); + } + } + } + } + catch (MalformedURLException ignored) { } } return null; @@ -763,7 +779,7 @@ public class MavenIndex { @Nullable @Override public Result compute() { - return Result.create(StringUtil.join(myRegisteredRepositoryIds, ","), new ModificationTracker() { + return Result.create(join(myRegisteredRepositoryIds, ","), new ModificationTracker() { @Override public long getModificationCount() { return myRegisteredRepositoryIds.hashCode(); From 3e6167906f5a5b3788da9a14933476eff2dc3691 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 25 Oct 2017 17:37:29 +0300 Subject: [PATCH 39/46] remove unused imports --- .../com/intellij/projectView/PackagesTreeStructureTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java b/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java index 97d40af133fb..8780963540bb 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java +++ b/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java @@ -28,12 +28,9 @@ import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.TestSourceBasedTestCase; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NonNls; -import org.jetbrains.concurrency.AsyncPromise; import javax.swing.*; -import java.awt.*; import java.io.IOException; -import java.util.concurrent.atomic.AtomicBoolean; public class PackagesTreeStructureTest extends TestSourceBasedTestCase { public void testPackageView() { From 447350c3ebaf740bee094eb64d81f15bb186c1fd Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Wed, 25 Oct 2017 17:22:07 +0300 Subject: [PATCH 40/46] EA-108201 - NPE: GotoActionModel$ActionWrapper.isAvailable --- .../src/com/intellij/ide/util/gotoByName/GotoActionModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index 0cf045b25fea..f44802f99650 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -503,7 +503,7 @@ public class GotoActionModel implements ChooseByNameModel, Comparator, D } public boolean isAvailable() { - return getPresentation().isEnabledAndVisible(); + return hasPresentation() && getPresentation().isEnabledAndVisible(); } public Presentation getPresentation() { From 5cdf13aba22220faa1d2dc08df10da7b9ccc7158 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Wed, 25 Oct 2017 17:29:23 +0300 Subject: [PATCH 41/46] EA-108201 - NPE: GotoActionModel$ActionWrapper.isAvailable --- .../src/com/intellij/ide/util/gotoByName/GotoActionModel.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index f44802f99650..ddba02847f1e 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -503,7 +503,8 @@ public class GotoActionModel implements ChooseByNameModel, Comparator, D } public boolean isAvailable() { - return hasPresentation() && getPresentation().isEnabledAndVisible(); + Presentation presentation = getPresentation(); + return presentation != null && presentation.isEnabledAndVisible(); } public Presentation getPresentation() { From e23c1051177342b622086cb50cf45e9b98030252 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 25 Oct 2017 15:16:20 +0200 Subject: [PATCH 42/46] "Go To Class" popup - changes in selection are reverted while changes are loading --- .../ide/util/gotoByName/ChooseByNameBase.java | 14 +++++++------- .../ide/util/gotoByName/SelectionPolicy.kt | 5 ++++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index 224e11524ff8..34669c2ed755 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -160,7 +160,7 @@ public abstract class ChooseByNameBase { static final boolean ourLoadNamesEachTime = FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping; private boolean myAlwaysHasMore = false; private Point myFocusPoint; - private SelectionSnapshot myCurrentChosenInfo; + @Nullable SelectionSnapshot currentChosenInfo; public boolean checkDisposed() { return myDisposedFlag; @@ -541,8 +541,8 @@ public abstract class ChooseByNameBase { myTextField.getDocument().addDocumentListener(new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { - SelectionPolicy toSelect = myCurrentChosenInfo != null && myCurrentChosenInfo.hasSamePattern(ChooseByNameBase.this) - ? myCurrentChosenInfo : SelectMostRelevant.INSTANCE; + SelectionPolicy toSelect = currentChosenInfo != null && currentChosenInfo.hasSamePattern(ChooseByNameBase.this) + ? PreserveSelection.INSTANCE : SelectMostRelevant.INSTANCE; rebuildList(toSelect, myRebuildDelay, ModalityState.current(), null); } }); @@ -648,7 +648,7 @@ public abstract class ChooseByNameBase { List chosenElements = getChosenElements(); if (!chosenElements.isEmpty()) { - myCurrentChosenInfo = new SelectionSnapshot(getTrimmedText(), new HashSet<>(chosenElements)); + currentChosenInfo = new SelectionSnapshot(getTrimmedText(), new HashSet<>(chosenElements)); } } }); @@ -1384,8 +1384,8 @@ public abstract class ChooseByNameBase { int count = elements.size(); if (count > lastCount) { setElementsToList(mySelectionPolicy, ContainerUtil.newArrayList(elements)); - if (myCurrentChosenInfo != null) { - mySelectionPolicy = myCurrentChosenInfo; + if (currentChosenInfo != null) { + mySelectionPolicy = PreserveSelection.INSTANCE; } } scheduleIncrementalListUpdate(elements, count); @@ -1565,7 +1565,7 @@ public abstract class ChooseByNameBase { ensureNamesLoaded(everywhere); indicator.setIndeterminate(true); final TooManyUsagesStatus tooManyUsagesStatus = TooManyUsagesStatus.createFor(indicator); - myCalcUsagesThread = new CalcElementsThread(text, everywhere, null, ModalityState.NON_MODAL, myCurrentChosenInfo) { + myCalcUsagesThread = new CalcElementsThread(text, everywhere, null, ModalityState.NON_MODAL, PreserveSelection.INSTANCE) { @Override protected boolean isOverflow(@NotNull Set elementsArray) { tooManyUsagesStatus.pauseProcessingIfTooManyUsages(); diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/SelectionPolicy.kt b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/SelectionPolicy.kt index 4a38f9b422db..08fc08ab6264 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/SelectionPolicy.kt +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/SelectionPolicy.kt @@ -33,11 +33,14 @@ internal data class SelectIndex(private val selectedIndex: Int) : SelectionPolic override fun performSelection(popup: ChooseByNameBase, model: SmartPointerListModel) = listOf(selectedIndex) } -internal data class SelectionSnapshot(val pattern: String, private val chosenElements: Set) : SelectionPolicy { +internal object PreserveSelection : SelectionPolicy { override fun performSelection(popup: ChooseByNameBase, model: SmartPointerListModel): List { + val chosenElements = popup.currentChosenInfo?.chosenElements ?: return emptyList() val items = model.items return items.indices.filter { items[it] in chosenElements } } +} +internal data class SelectionSnapshot(private val pattern: String, internal val chosenElements: Set) { fun hasSamePattern(popup: ChooseByNameBase) = popup.transformPattern(pattern) == popup.transformPattern(popup.trimmedText) } \ No newline at end of file From 2b2f31600c74583aed163e04dab5d90afaaa318e Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 25 Oct 2017 15:38:47 +0200 Subject: [PATCH 43/46] don't prefer case-insensitive-prefix matches in goto file (IDEA-180961) --- .../com/intellij/java/navigation/ChooseByNameTest.groovy | 6 ++++++ .../src/com/intellij/ide/actions/GotoFileItemProvider.java | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/java/navigation/ChooseByNameTest.groovy b/java/java-tests/testSrc/com/intellij/java/navigation/ChooseByNameTest.groovy index 426a0abc1445..893afd7dfeaa 100644 --- a/java/java-tests/testSrc/com/intellij/java/navigation/ChooseByNameTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/navigation/ChooseByNameTest.groovy @@ -55,6 +55,12 @@ class ChooseByNameTest extends LightCodeInsightFixtureTestCase { assert elements == [startMatch, wordSkipMatch, camelMatch, middleMatch] } + void "test goto file order by matching degree"() { + def camel = addEmptyFile("ServiceAccessor.java") + def startLower = addEmptyFile("sache.txt") + assert gotoFile('SA') == [camel, startLower] + } + void "test disprefer start matches when prefix starts with asterisk"() { def startMatch = myFixture.addClass('class ITable {}') def endMatch = myFixture.addClass('class HappyHippoIT {}') diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java index f19b929fd8ab..9a81f6755a2a 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoFileItemProvider.java @@ -317,8 +317,8 @@ public class GotoFileItemProvider extends DefaultChooseByNameItemProvider { List> groups = new ArrayList<>(); Comparator comparator = (mr1, mr2) -> { - boolean exactPrefix1 = StringUtil.startsWithIgnoreCase(mr1.elementName, patternSuffix); - boolean exactPrefix2 = StringUtil.startsWithIgnoreCase(mr2.elementName, patternSuffix); + boolean exactPrefix1 = StringUtil.startsWith(mr1.elementName, patternSuffix); + boolean exactPrefix2 = StringUtil.startsWith(mr2.elementName, patternSuffix); if (exactPrefix1 && exactPrefix2) return 0; if (exactPrefix1 != exactPrefix2) return exactPrefix1 ? -1 : 1; return mr1.compareDegrees(mr2, preferStartMatches); From 3d2ef05dd4730bd066fbe65ec4111e4866223361 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 25 Oct 2017 18:00:11 +0300 Subject: [PATCH 44/46] IDEA-180845 Tasks Servers dialog issues: jira icons --- plugins/tasks/tasks-core/src/icons/jira.png | Bin 232 -> 326 bytes plugins/tasks/tasks-core/src/icons/jira@2x.png | Bin 410 -> 636 bytes .../tasks/tasks-core/src/icons/jira@2x_dark.png | Bin 636 -> 410 bytes .../tasks/tasks-core/src/icons/jira_dark.png | Bin 326 -> 232 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/plugins/tasks/tasks-core/src/icons/jira.png b/plugins/tasks/tasks-core/src/icons/jira.png index cbf3252b80f3f3a7b70ae77e88c473c6167c4c0f..f6f1f416b09f066949e4db7db84f7cf7f040b147 100644 GIT binary patch delta 300 zcmV+{0n`5I0mcH5BYy!6Nkl86CjocVkRI~ zhpEG5fD;h^1LA{F{#qcu3&gTOJQ;}p192Wc1Ehd>JrHLhxd?`Rpe{1TWx#SE_6K57 zESh0h0Ej(+co{YWjzXRI1L|ZysPjQM28bnq_zP6cX>11gL4PGdcn=V>LS3~5h}nU7 z6Ow!ct}vL7q-Y5cvp_?C3X=F*e1XUY#JiCcZwC1niGKnX#rVxflTXf&Hps2?1dM0000O;m|+RTvQT^-ieY?9LYj+#_$d&dz+%94 zs9Z5V13aJ#8?neWLghSgX$IMvg3p;y?}5~uz$OWE;!~)?MkIbeR1C(yj?e$dVXzB| zWuanEafSm>kPoUDrf3&b468UUKgyzcWfz)ekeoK5sMJQ&L`J-3w9rO3B!yVbd{Eow zVsXAKF$N$vm0xdmgBS$YW2EbzgNeu1^s^?w+{;TWk@K(lJ00000NkvXX Hu0mjfWUE*@ diff --git a/plugins/tasks/tasks-core/src/icons/jira@2x.png b/plugins/tasks/tasks-core/src/icons/jira@2x.png index 351ed1724d461925843753a34afc1b1dc33fb3f0..33cda03b2b276db88db66f34292e64504352c4a0 100644 GIT binary patch delta 612 zcmV-q0-ODs1N;P#BYy%zNkly{`DJkqs z)9}@lEaaN9F}tbRP*#+z6lP(88J7}?B9RPHMrLDjEyR@Z`k#8fdODrM`@Y{1W%28) zbDqopJ?DAOIiJU}EYD-&d2#|O>O1X{1Ac*jpdW< zb3ahp_hF6C4-nu~fJm~c2{_GG!nY-Z8e4HJ$GAO+5`VysCa|ddI1oV{pt3oYFEKYK zVJe;Xsssm`g0<*8$un^s3zET>CXtF`@Yd9Oz(=&ydOF0Rm1gom!VwqCz&!%8O}~gZ z!PHJ&cL)##8T1eW%D@p_FhWGf9U@vx3wQ(3am`xVFnq`}hCIoy{1fEmaskWlWgn%(c;AVxL yS7A46Lcov|^qLA#wo9jLcY@LGSirOUcYF)%&%vaRQa@b)00007q%YJz5@`B7d2(JlA@0FvSlhf-^R{fJ%^5T72Y zKcra!G52}_QwZ+#bFG52my<%6Qwso7x?D74TBkoyr8A{)EdadcVZl6Pd7q%YJz5@`B7d2(JlA@0FvSlhf-^R{fJ%^5T72Y zKcra!G52}_QwZ+#bFG52my<%6Qwso7x?D74TBkoyr8A{)EdadcVZl6Pdy{`DJkqs z)9}@lEaaN9F}tbRP*#+z6lP(88J7}?B9RPHMrLDjEyR@Z`k#8fdODrM`@Y{1W%28) zbDqopJ?DAOIiJU}EYD-&d2#|O>O1X{1Ac*jpdW< zb3ahp_hF6C4-nu~fJm~c2{_GG!nY-Z8e4HJ$GAO+5`VysCa|ddI1oV{pt3oYFEKYK zVJe;Xsssm`g0<*8$un^s3zET>CXtF`@Yd9Oz(=&ydOF0Rm1gom!VwqCz&!%8O}~gZ z!PHJ&cL)##8T1eW%D@p_FhWGf9U@vx3wQ(3am`xVFnq`}hCIoy{1fEmaskWlWgn%(c;AVxL yS7A46Lcov|^qLA#wo9jLcY@LGSirOUcYF)%&%vaRQa@b)0000O;m|+RTvQT^-ieY?9LYj+#_$d&dz+%94 zs9Z5V13aJ#8?neWLghSgX$IMvg3p;y?}5~uz$OWE;!~)?MkIbeR1C(yj?e$dVXzB| zWuanEafSm>kPoUDrf3&b468UUKgyzcWfz)ekeoK5sMJQ&L`J-3w9rO3B!yVbd{Eow zVsXAKF$N$vm0xdmgBS$YW2EbzgNeu1^s^?w+{;TWk@K(lJ00000NkvXX Hu0mjfWUE*@ delta 300 zcmV+{0n`5I0mcH5BYy!6Nkltncrp<`4E zSTw`101$fs@iJ@%9ECdZ2h_=aQ0Iei3=m5I@fWC?)7T8~gMUhb@E#y$g}Q1B5VHgE zCM5X?TwyRDNzoD@W`TzO6eRJr_yUm)h<76?-VE|D68{7&it(ibPN*&a(eQpC<|C92 zU>M}=iD(AcAgjS=05cFD2jXZT?m;r(4iIw?V?Z=i!(SkF1LCDfhGY|Cz-Fl84?rve y#5_R!5-A)A8YOTYs(1~O*aT>TI*8K%axnnSb}&H Date: Wed, 25 Oct 2017 17:09:42 +0200 Subject: [PATCH 45/46] [platform] overwrites corrupted action script files (EA-110095) --- .../startup/StartupActionScriptManager.java | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/platform/bootstrap/src/com/intellij/ide/startup/StartupActionScriptManager.java b/platform/bootstrap/src/com/intellij/ide/startup/StartupActionScriptManager.java index b890c067198b..6d4688a08016 100644 --- a/platform/bootstrap/src/com/intellij/ide/startup/StartupActionScriptManager.java +++ b/platform/bootstrap/src/com/intellij/ide/startup/StartupActionScriptManager.java @@ -1,21 +1,8 @@ -/* - * Copyright 2000-2017 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. - */ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide.startup; import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.util.io.ZipUtil; import org.jetbrains.annotations.NotNull; @@ -60,8 +47,16 @@ public class StartupActionScriptManager { } } else { - List script = loadActionScript(); - script.addAll(commands); + List script; + try { + script = loadActionScript(); + script.addAll(commands); + } + catch (ObjectStreamException e) { + Logger.getInstance(StartupActionScriptManager.class).warn(e); + script = new ArrayList<>(commands); + } + saveActionScript(script); } } @@ -86,7 +81,7 @@ public class StartupActionScriptManager { } } catch (ReflectiveOperationException e) { - throw new IOException("Stream error: " + scriptFile, e); + throw (StreamCorruptedException)new StreamCorruptedException("Stream error: " + scriptFile).initCause(e); } } From 55a4852f19010b2fd0607a315ce958f2d2ba5df4 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 25 Oct 2017 17:57:18 +0300 Subject: [PATCH 46/46] IDEA-181071 context submenu arrow icon is low res on Retina --- platform/icons/src/mac/tree_black_right_arrow.png | Bin 0 -> 147 bytes .../icons/src/mac/tree_black_right_arrow@2x.png | Bin 0 -> 231 bytes .../com/intellij/ide/ui/laf/LafManagerImpl.java | 14 +------------- .../ide/ui/laf/intellijlaf_mac.properties | 1 + .../util/src/com/intellij/icons/AllIcons.java | 1 + 5 files changed, 3 insertions(+), 13 deletions(-) create mode 100644 platform/icons/src/mac/tree_black_right_arrow.png create mode 100644 platform/icons/src/mac/tree_black_right_arrow@2x.png diff --git a/platform/icons/src/mac/tree_black_right_arrow.png b/platform/icons/src/mac/tree_black_right_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..0de0b214b7291ce71e93e2b529890c822239af95 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqhQJyZ2Ar-fhfBgS%&%9CMTtR86 zEz^-@JQfVQ9{ms4BhiuC5z2Gue&Y_#j>?Wep2O!GECf4d0$Jr!hF$SYg=_+w1&WHT t1wIQFeKt~|%QF=+q* literal 0 HcmV?d00001 diff --git a/platform/icons/src/mac/tree_black_right_arrow@2x.png b/platform/icons/src/mac/tree_black_right_arrow@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5e76166f96b3e5cb26cb5da92da3aafbb6b9b72c GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4f>pWc?Ln>}1|M>sko>|v``7Tdc zX{jyKk!3t7Of_u(+aDcu&~fH&cKl&2V9sdBzm>P`VY#)WPq()reJM%^bkecldbJ&mQfYjtOZPeH0spC0fc*W$0u|PPpq59UQNBRQinUXlO z-0t})Tw9t}w43S3yenrE^cyXhr!83#%CVK%P~Mb#VXA|U|JfwrkPEW|_b!nCQYy!= Y?RL`n^gEIEK$kOky85}Sb4q9e04)GgAOHXW literal 0 HcmV?d00001 diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java index ddde3ece8021..9489edb09273 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java @@ -394,19 +394,7 @@ public final class LafManagerImpl extends LafManager implements PersistentStateC @Nullable private static Icon getAquaMenuInvertedIcon() { if (UIUtil.isUnderAquaLookAndFeel() || (SystemInfo.isMac && UIUtil.isUnderIntelliJLaF())) { - final Icon arrow = (Icon)UIManager.get("Menu.arrowIcon"); - if (arrow == null) return null; - - try { - final Method method = ReflectionUtil.getMethod(arrow.getClass(), "getInvertedIcon"); - if (method != null) { - return (Icon)method.invoke(arrow); - } - return null; - } - catch (InvocationTargetException | IllegalAccessException e1) { - return null; - } + return AllIcons.Mac.Tree_white_right_arrow; } return null; } 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 8cd5caadc77b..6d68ff60e70b 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 @@ -40,6 +40,7 @@ Menu.border=com.intellij.ide.ui.laf.intellij.MacIntelliJMenuItemBorder PopupMenu.background=f6f6f6 MenuItem.background=f6f6f6 Menu.background=f6f6f6 +Menu.arrowIcon=AllIcons.Mac.Tree_black_right_arrow SplitPane.highlight=ececec diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java index f6799cdf6668..98d47f4c8366 100644 --- a/platform/util/src/com/intellij/icons/AllIcons.java +++ b/platform/util/src/com/intellij/icons/AllIcons.java @@ -807,6 +807,7 @@ public class AllIcons { public static class Mac { public static final Icon AppIconOk512 = IconLoader.getIcon("/mac/appIconOk512.png"); // 55x55 public static final Icon Text = IconLoader.getIcon("/mac/text.gif"); // 32x32 + public static final Icon Tree_black_right_arrow = IconLoader.getIcon("/mac/tree_black_right_arrow.png"); // 11x11 public static final Icon Tree_white_down_arrow = IconLoader.getIcon("/mac/tree_white_down_arrow.png"); // 11x11 public static final Icon Tree_white_right_arrow = IconLoader.getIcon("/mac/tree_white_right_arrow.png"); // 11x11 public static final Icon YosemiteOptionButtonSelector = IconLoader.getIcon("/mac/yosemiteOptionButtonSelector.png"); // 8x12