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)"); 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-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); } 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/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; } 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/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{}"); + } +} 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..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 {}') @@ -419,6 +425,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/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java b/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java index c1c469a371fa..8780963540bb 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java +++ b/java/java-tests/testSrc/com/intellij/projectView/PackagesTreeStructureTest.java @@ -218,7 +218,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/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/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); } } 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; 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 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..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,20 +131,23 @@ public class ExtensionsAreaImpl implements ExtensionsArea { @Override public void registerExtension(@NotNull final PluginDescriptor pluginDescriptor, @NotNull final Element extensionElement, String ns) { - final PluginId pluginId = pluginDescriptor.getPluginId(); + String epName = extractEPName(extensionElement, ns); + registerExtension(getExtensionPoint(epName), pluginDescriptor, extensionElement); + } + // 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; } - 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"); + 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)); } @@ -152,7 +155,7 @@ public class ExtensionsAreaImpl implements ExtensionsArea { adapter = new ExtensionComponentAdapter(extensionPoint.getClassName(), extensionElement, myPicoContainer, pluginDescriptor, true); } myPicoContainer.registerComponent(adapter); - extensionPoint.registerExtensionAdapter(adapter); + ((ExtensionPointImpl)extensionPoint).registerExtensionAdapter(adapter); } private static boolean shouldDeserializeInstance(Element extensionElement) { 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 000000000000..0de0b214b729 Binary files /dev/null and b/platform/icons/src/mac/tree_black_right_arrow.png differ 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 000000000000..5e76166f96b3 Binary files /dev/null and b/platform/icons/src/mac/tree_black_right_arrow@2x.png differ 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 a50212887828..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,18 +27,22 @@ 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, 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, 30); + public static final RunDashboardRunConfigurationStatus CONFIGURED = new RunDashboardRunConfigurationStatus( + 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() { @@ -49,10 +53,14 @@ public class RunDashboardRunConfigurationStatus { return myIcon; } + public int getPriority() { + return myPriority; + } + 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/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/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); } 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; 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 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()); + } } 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/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(); } 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..5cccd76eaf5d 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 @@ -16,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 @@ -26,7 +24,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 +82,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 +97,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 +237,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 +336,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 +351,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 +562,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 +576,7 @@ open class RunManagerImpl(internal val project: Project) : RunManagerEx(), Persi } } } - immutableSortedSettingsList = null + listManager.immutableSortedSettingsList = null selectedConfigurationId = parentNode.getAttributeValue(SELECTED_ATTR) } @@ -747,7 +635,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() @@ -817,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 @@ -880,10 +768,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() } } @@ -991,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 @@ -1044,7 +884,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 +932,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 +968,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) { 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); } 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); 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/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/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index 0cf045b25fea..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 getPresentation().isEnabledAndVisible(); + Presentation presentation = getPresentation(); + return presentation != null && presentation.isEnabledAndVisible(); } public Presentation getPresentation() { 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 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..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 @@ -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,26 +75,13 @@ 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); + newSettings.resetDeprecatedFields(); // Clean up if imported from legacy settings ((CodeStyleSchemeImpl)scheme).setCodeStyleSettings(newSettings); return scheme; } 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-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) { 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/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]; 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..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 @@ -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,8 @@ 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.*; import javax.swing.plaf.basic.BasicTreeUI; @@ -42,6 +46,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 +54,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(); @@ -790,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 @@ -815,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); 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 */ 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/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/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/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 = 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(); } } } 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(); 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()); } diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties index b3a61029b0a4..a0b130027998 100644 --- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties +++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties @@ -407,8 +407,9 @@ run.dashboard.previous.configuration.action.name=Previous Started Configuration run.dashboard.next.configuration.action.name=Next Started Configuration run.dashboard.remove.configuration.dialog.title=Remove Configuration run.dashboard.remove.configuration.dialog.message=Are you sure to remove selected configuration(s)? -run.dashboard.started.group.name=Started -run.dashboard.stopped.group.name=Stopped +run.dashboard.started.group.name=Running +run.dashboard.stopped.group.name=Finished +run.dashboard.configured.group.name=Configured run.dashboard.failed.group.name=Failed run.dashboard.group.configurations.title=Group Configurations run.dashboard.group.configurations.label=Group Name: 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 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/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()); 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); 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 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 diff --git a/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java b/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java index 19ec628047e2..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 && hashCode() != o.hashCode()) return false; - if (o == null || !(o instanceof CharSequence)) return false; - return StringUtil.equals(this, (CharSequence)o); - } - private transient int hash; @Override public int hashCode() { 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; } 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" + 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("]", "|]"); } } 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(); diff --git a/plugins/tasks/tasks-core/src/icons/jira.png b/plugins/tasks/tasks-core/src/icons/jira.png index cbf3252b80f3..f6f1f416b09f 100644 Binary files a/plugins/tasks/tasks-core/src/icons/jira.png and b/plugins/tasks/tasks-core/src/icons/jira.png differ diff --git a/plugins/tasks/tasks-core/src/icons/jira@2x.png b/plugins/tasks/tasks-core/src/icons/jira@2x.png index 351ed1724d46..33cda03b2b27 100644 Binary files a/plugins/tasks/tasks-core/src/icons/jira@2x.png and b/plugins/tasks/tasks-core/src/icons/jira@2x.png differ diff --git a/plugins/tasks/tasks-core/src/icons/jira@2x_dark.png b/plugins/tasks/tasks-core/src/icons/jira@2x_dark.png index 33cda03b2b27..351ed1724d46 100644 Binary files a/plugins/tasks/tasks-core/src/icons/jira@2x_dark.png and b/plugins/tasks/tasks-core/src/icons/jira@2x_dark.png differ diff --git a/plugins/tasks/tasks-core/src/icons/jira_dark.png b/plugins/tasks/tasks-core/src/icons/jira_dark.png index 876771437d14..cbf3252b80f3 100644 Binary files a/plugins/tasks/tasks-core/src/icons/jira_dark.png and b/plugins/tasks/tasks-core/src/icons/jira_dark.png differ 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 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; }