Merge remote-tracking branch 'origin/master'
@@ -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)");
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -393,13 +393,21 @@ public class DataFlowInspectionBase extends AbstractBaseJavaLocalInspectionTool
|
||||
private static void reportAlwaysFailingCalls(ProblemsHolder holder,
|
||||
DataFlowInstructionVisitor visitor,
|
||||
HashSet<PsiElement> 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<MethodContract> 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<PsiCall> getAlwaysFailingCalls() {
|
||||
return StreamEx.ofKeys(myFailingCalls, v -> v).map(MethodCallInstruction::getCallExpression).toList();
|
||||
Map<PsiCall, List<MethodContract>> getAlwaysFailingCalls() {
|
||||
return StreamEx.ofKeys(myFailingCalls, v -> v)
|
||||
.mapToEntry(MethodCallInstruction::getCallExpression, MethodCallInstruction::getContracts).toMap();
|
||||
}
|
||||
|
||||
boolean isAlwaysReturnsNotNull(Instruction[] instructions) {
|
||||
|
||||
@@ -196,7 +196,7 @@ public class DuplicatesFinder {
|
||||
ArrayList<PsiElement> 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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<PsiElement, PsiComment> 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<String> findUrlForClass(@NotNull PsiClass aClass) {
|
||||
String qName = aClass.getQualifiedName();
|
||||
|
||||
@@ -3,7 +3,7 @@ public class X {
|
||||
<caret>int i;
|
||||
|
||||
@org.testng.annotations.BeforeMethod
|
||||
public void setUp() throws Exception {
|
||||
public void setUp() {
|
||||
i = 7;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,6 @@ public final class ArrayLength {
|
||||
System.out.println("Impossible");
|
||||
}
|
||||
Arrays.fill(x, -1);
|
||||
Arrays.<warning descr="The call to 'fill' always fails, according to its method contracts">fill</warning>(x, -1, -1, -1);
|
||||
Arrays.<warning descr="The call to 'fill' always fails as index is out of bounds">fill</warning>(x, -1, -1, -1);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
public class CustomContracts {
|
||||
public void testSubstring(String s) {
|
||||
if (s.<warning descr="The call to 'substring' always fails, according to its method contracts">substring</warning>(-1).length() == 0) {
|
||||
if (s.<warning descr="The call to 'substring' always fails as index is out of bounds">substring</warning>(-1).length() == 0) {
|
||||
System.out.println("Oops");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ForEachOverEmptyCollection {
|
||||
}
|
||||
if(!hasItem) {
|
||||
System.out.println(
|
||||
list.<warning descr="The call to 'get' always fails, according to its method contracts">get</warning>(<warning descr="Condition 'max == null' is always 'true'">max == null</warning> ? 0 : 1));
|
||||
list.<warning descr="The call to 'get' always fails as index is out of bounds">get</warning>(<warning descr="Condition 'max == null' is always 'true'">max == null</warning> ? 0 : 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,13 +196,13 @@ public class LongRangeKnownMethods {
|
||||
|
||||
void testEmptyListGet(List<String> list) {
|
||||
if (list.isEmpty()) {
|
||||
System.out.println(list.<warning descr="The call to 'get' always fails, according to its method contracts">get</warning>(0));
|
||||
System.out.println(list.<warning descr="The call to 'get' always fails as index is out of bounds">get</warning>(0));
|
||||
}
|
||||
}
|
||||
|
||||
void testBoundError(List<String> list) {
|
||||
if (list.size() < 10) {
|
||||
System.out.println(list.<warning descr="The call to 'get' always fails, according to its method contracts">get</warning>(10));
|
||||
System.out.println(list.<warning descr="The call to 'get' always fails as index is out of bounds">get</warning>(10));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.awe<caret>some;");
|
||||
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.awe<caret>some{}");
|
||||
myFixture.launchAction(myFixture.findSingleIntention("Add Javadoc"));
|
||||
myFixture.checkResult("/**\n" +
|
||||
" * \n" +
|
||||
" */\n" +
|
||||
"module org.some.awesome{}");
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<ActionCommand> script = loadActionScript();
|
||||
script.addAll(commands);
|
||||
List<ActionCommand> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 231 B |
@@ -35,6 +35,8 @@ public interface RunDashboardGroupingRule extends TreeAction {
|
||||
return res != 0 ? res : (o1.getName().compareTo(o2.getName()));
|
||||
};
|
||||
|
||||
Comparator<RunDashboardGroup> 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<RunDashboardGroup> getGroupComparator() {
|
||||
return GROUP_NAME_COMPARATOR;
|
||||
}
|
||||
|
||||
interface Priorities {
|
||||
int BY_RUN_CONFIG = 200;
|
||||
int BY_FOLDER = 400;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<Integer> caretRestoreOffset = new Ref<>(-1);
|
||||
CodeEditUtil.setNodeReformatStrategy(node -> node.getTextRange().getStartOffset() >= startReformatOffset);
|
||||
try {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -80,8 +80,14 @@ class RunConfigurationNode extends AbstractTreeNode<Pair<RunnerAndConfigurationS
|
||||
RunnerAndConfigurationSettings configurationSettings = getConfigurationSettings();
|
||||
//noinspection ConstantConditions
|
||||
boolean isStored = RunManager.getInstance(getProject()).hasSettings(configurationSettings);
|
||||
presentation.addText(configurationSettings.getName(),
|
||||
isStored ? SimpleTextAttributes.REGULAR_ATTRIBUTES : SimpleTextAttributes.GRAY_ATTRIBUTES);
|
||||
SimpleTextAttributes nameAttributes;
|
||||
if (isStored) {
|
||||
nameAttributes = getContent() != null ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES;
|
||||
}
|
||||
else {
|
||||
nameAttributes = SimpleTextAttributes.GRAYED_BOLD_ATTRIBUTES;
|
||||
}
|
||||
presentation.addText(configurationSettings.getName(), nameAttributes);
|
||||
Icon icon = null;
|
||||
RunDashboardRunConfigurationStatus status = myContributor != null ? myContributor.getStatus(this) :
|
||||
RunDashboardRunConfigurationStatus.getStatus(this);
|
||||
|
||||
@@ -33,6 +33,10 @@ public class RunDashboardGroupImpl<T> implements RunDashboardGroup {
|
||||
myIcon = icon;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return myValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
@@ -50,6 +54,9 @@ public class RunDashboardGroupImpl<T> implements RunDashboardGroup {
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof RunDashboardGroupImpl) {
|
||||
return myValue.equals(((RunDashboardGroupImpl)obj).myValue);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<RunDashboardGroup> getGroupComparator() {
|
||||
//noinspection unchecked
|
||||
return Comparator.comparing(group -> ((RunDashboardGroupImpl<RunDashboardRunConfigurationStatus>)group).getValue().getPriority());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<BeforeRunTask<*>>, templateTasks: List<BeforeRunTask<*>>, ownIsOnlyEnabled: Boolean, isDisableTemplateTasks: Boolean): MutableList<BeforeRunTask<*>> {
|
||||
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<BeforeRunTask<*>> {
|
||||
return templateConfiguration.beforeRunTasks.nullize() ?: getHardcodedBeforeRunTasks(templateConfiguration)
|
||||
}
|
||||
|
||||
internal fun getHardcodedBeforeRunTasks(configuration: RunConfiguration): List<BeforeRunTask<*>> {
|
||||
var result: MutableList<BeforeRunTask<*>>? = 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<BeforeRunTask<*>>()
|
||||
}
|
||||
result.add(task)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.orEmpty()
|
||||
}
|
||||
@@ -90,17 +90,6 @@ extends BeforeRunTaskProvider<RunConfigurationBeforeRunProvider.RunConfigurableB
|
||||
@Override
|
||||
@Nullable
|
||||
public RunConfigurableBeforeRunTask createTask(@NotNull RunConfiguration runConfiguration) {
|
||||
return createTask(runConfiguration, runConfiguration.getProject().isInitialized() ? RunManagerImpl.getInstanceImpl(runConfiguration.getProject()) : null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RunConfigurableBeforeRunTask createTask(@NotNull RunConfiguration runConfiguration, @Nullable RunManagerImpl runManager) {
|
||||
if (runManager != null) {
|
||||
List<RunnerAndConfigurationSettings> configurations = runManager.getAllSettings();
|
||||
if (configurations.isEmpty() || (configurations.size() == 1 && configurations.get(0).getConfiguration() == runConfiguration)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new RunConfigurableBeforeRunTask();
|
||||
}
|
||||
|
||||
|
||||
@@ -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<String, RunnerAndConfigurationSettings>()
|
||||
|
||||
private val customOrder = ObjectIntHashMap<String>()
|
||||
|
||||
private var isCustomOrderApplied = true
|
||||
set(value) {
|
||||
if (field != value) {
|
||||
field = value
|
||||
if (!value) {
|
||||
immutableSortedSettingsList = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Volatile
|
||||
var immutableSortedSettingsList: List<RunnerAndConfigurationSettings>? = emptyList()
|
||||
|
||||
fun setOrder(comparator: Comparator<RunnerAndConfigurationSettings>?) {
|
||||
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<String>) {
|
||||
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<RunnerAndConfigurationSettings> {
|
||||
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<String>()
|
||||
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<RunnerAndConfigurationSettings>) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String, ConfigurationType>()
|
||||
|
||||
@Suppress("LeakingThis")
|
||||
private val listManager = RunConfigurationListManagerHelper(this)
|
||||
|
||||
private val templateIdToConfiguration = THashMap<String, RunnerAndConfigurationSettingsImpl>()
|
||||
// template configurations are not included here
|
||||
private val idToSettings = LinkedHashMap<String, RunnerAndConfigurationSettings>()
|
||||
private val idToSettings: LinkedHashMap<String, RunnerAndConfigurationSettings>
|
||||
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<String>()
|
||||
private val recentlyUsedTemporaries = ArrayList<RunnerAndConfigurationSettings>()
|
||||
|
||||
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<RunnerAndConfigurationSettings>?) {
|
||||
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<RunnerAndConfigurationSettings>? = emptyList()
|
||||
|
||||
fun requestSort() {
|
||||
lock.write {
|
||||
if (customOrder.isEmpty) {
|
||||
sortAlphabetically()
|
||||
}
|
||||
else {
|
||||
isCustomOrderApplied = false
|
||||
}
|
||||
immutableSortedSettingsList = null
|
||||
allSettings
|
||||
listManager.requestSort()
|
||||
}
|
||||
}
|
||||
|
||||
override val allSettings: List<RunnerAndConfigurationSettings>
|
||||
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<String>()
|
||||
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<BeforeRunTask<*>>,
|
||||
templateTasks: List<BeforeRunTask<*>>,
|
||||
ownIsOnlyEnabled: Boolean,
|
||||
isDisableTemplateTasks: Boolean): MutableList<BeforeRunTask<*>> {
|
||||
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<BeforeRunTask<*>> {
|
||||
return templateConfiguration.beforeRunTasks.nullize() ?: getHardcodedBeforeRunTasks(templateConfiguration)
|
||||
}
|
||||
|
||||
private fun getHardcodedBeforeRunTasks(configuration: RunConfiguration): List<BeforeRunTask<*>> {
|
||||
var result: MutableList<BeforeRunTask<*>>? = 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<BeforeRunTask<*>>()
|
||||
}
|
||||
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<RunnerAndConfigurationSettings>) {
|
||||
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<RunnerAndConfigurationSettings>()
|
||||
var selectedConfigurationWasRemoved = false
|
||||
lock.write {
|
||||
immutableSortedSettingsList = null
|
||||
listManager.immutableSortedSettingsList = null
|
||||
|
||||
val iterator = idToSettings.values.iterator()
|
||||
for (settings in iterator) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -317,8 +317,8 @@ public class GotoFileItemProvider extends DefaultChooseByNameItemProvider {
|
||||
List<List<String>> groups = new ArrayList<>();
|
||||
|
||||
Comparator<MatchResult> 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);
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<Object> 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<Object> elementsArray) {
|
||||
tooManyUsagesStatus.pauseProcessingIfTooManyUsages();
|
||||
|
||||
@@ -503,7 +503,8 @@ public class GotoActionModel implements ChooseByNameModel, Comparator<Object>, D
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return getPresentation().isEnabledAndVisible();
|
||||
Presentation presentation = getPresentation();
|
||||
return presentation != null && presentation.isEnabledAndVisible();
|
||||
}
|
||||
|
||||
public Presentation getPresentation() {
|
||||
|
||||
@@ -33,11 +33,14 @@ internal data class SelectIndex(private val selectedIndex: Int) : SelectionPolic
|
||||
override fun performSelection(popup: ChooseByNameBase, model: SmartPointerListModel<Any>) = listOf(selectedIndex)
|
||||
}
|
||||
|
||||
internal data class SelectionSnapshot(val pattern: String, private val chosenElements: Set<Any>) : SelectionPolicy {
|
||||
internal object PreserveSelection : SelectionPolicy {
|
||||
override fun performSelection(popup: ChooseByNameBase, model: SmartPointerListModel<Any>): List<Int> {
|
||||
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<Any>) {
|
||||
fun hasSamePattern(popup: ChooseByNameBase) = popup.transformPattern(pattern) == popup.transformPattern(popup.trimmedText)
|
||||
}
|
||||
@@ -51,7 +51,7 @@ public class CodeStyleSchemeXmlImporter extends CodeStyleSettingsLoader implemen
|
||||
@NotNull CodeStyleScheme currentScheme,
|
||||
@NotNull SchemeFactory<CodeStyleScheme> schemeFactory) throws SchemeImportException {
|
||||
Element rootElement = SchemeImportUtil.loadSchemeDom(selectedFile);
|
||||
Element schemeRoot = getSchemeRoot(rootElement);
|
||||
Element schemeRoot = findSchemeRoot(rootElement);
|
||||
final Pair<String, CodeStyleScheme> 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3636,7 +3636,14 @@ public class AbstractTreeUi {
|
||||
|
||||
if (descriptor.getChildrenSortingStamp() >= getComparatorStamp() && !forceSort) return;
|
||||
if (!children.isEmpty()) {
|
||||
getBuilder().sortChildren(myNodeComparator, node, (ArrayList<TreeNode>)children);
|
||||
try {
|
||||
getBuilder().sortChildren(myNodeComparator, node, (ArrayList<TreeNode>)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) {
|
||||
|
||||
@@ -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<WeakReference<ActionCallback>> CALLBACK = Key.create("Callback");
|
||||
public static final Key<Function<TreeVisitor, Promise<TreePath>>> VISIT = Key.create("TreeVisit");
|
||||
private static final Key<Promise<Void>> 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<TreeVisitor, Promise<TreePath>> acceptor = UIUtil.getClientProperty(tree, VISIT);
|
||||
Function<TreeVisitor, Promise<TreePath>> acceptor = getTreeAcceptor(tree);
|
||||
if (acceptor == null) return false;
|
||||
|
||||
expand(tree, promise -> expand(acceptor, tree).processed(expanded -> {
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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<Integer> NUMBERS = JBIterable.generate(0, i -> i + 1);
|
||||
private static final Key<Function<TreeVisitor, Promise<TreePath>>> TREE_ACCEPTOR = Key.create("TreeAcceptor");
|
||||
|
||||
private TreeUtil() {}
|
||||
|
||||
@Nullable
|
||||
public static Function<TreeVisitor, Promise<TreePath>> getTreeAcceptor(@NotNull JTree tree) {
|
||||
return UIUtil.getClientProperty(tree, TREE_ACCEPTOR);
|
||||
}
|
||||
|
||||
public static void setTreeAcceptor(@NotNull JTree tree, @Nullable Function<TreeVisitor, Promise<TreePath>> acceptor) {
|
||||
UIUtil.putClientProperty(tree, TREE_ACCEPTOR, acceptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JBTreeTraverser<TreePath> 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<JTree> promiseExpandAll(@NotNull JTree tree) {
|
||||
AsyncPromise<JTree> 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<TreeVisitor, Promise<TreePath>> 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<JTree> promiseExpand(@NotNull JTree tree, int depth) {
|
||||
AsyncPromise<JTree> 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<TreeVisitor, Promise<TreePath>> 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<TreeVisitor, Promise<TreePath>> acceptor, int depth, Runnable onDone) {
|
||||
Promise<TreePath> 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);
|
||||
|
||||
@@ -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<String> 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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 =
|
||||
"<html><span style='font-size:x-small'>When enabled, the IDE UI scaling honors per-monitor DPI.<br>" +
|
||||
(SystemInfo.isWindows ?
|
||||
"To " + (ENABLED ? "disable" : "enable") + " set the JVM option <code>-Dsun.java2d.uiScale.enabled=" +
|
||||
(ENABLED ? "false" : "true") + "</code> and restart.</span></html>";
|
||||
(ENABLED ? "false" : "true") + "</code> and restart.</span></html>" :
|
||||
"The mode can not be changed on this platform.");
|
||||
|
||||
private final String SYS_SCALE_TEXT = "Monitor scale";
|
||||
private final String SYS_SCALE_DESC =
|
||||
|
||||
@@ -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<CharSequence> 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++) {
|
||||
|
||||
@@ -69,7 +69,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
private final ConcurrentIntObjectMap<VirtualFileSystemEntry> myRootsById = ContainerUtil.createConcurrentIntObjectMap(10, 0.4f, JobSchedulerImpl.CORES_COUNT);
|
||||
|
||||
// FS roots must be in this map too. findFileById() relies on this.
|
||||
private final ConcurrentIntObjectMap<VirtualFileSystemEntry> myIdToDirCache = ContainerUtil.createConcurrentIntObjectSoftValueMap();
|
||||
private final ConcurrentIntObjectMap<VirtualFileSystemEntry> 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<ConcurrentIntObjectMap.IntEntry<VirtualFileSystemEntry>> iterator = myIdToDirCache.entries().iterator(); iterator.hasNext(); ) {
|
||||
ConcurrentIntObjectMap.IntEntry<VirtualFileSystemEntry> entry = iterator.next();
|
||||
int id = entry.getKey();
|
||||
if (!myRootsById.containsKey(id)) {
|
||||
myIdToDirCache.remove(id);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -55,10 +55,16 @@ public abstract class AbstractTreeNodeVisitor<T> 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());
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -64,6 +64,8 @@ dataflow.message.npe.field.access=Dereference of <code>#ref</code> #loc may prod
|
||||
dataflow.message.cce=Casting <code>{0}</code> to <code>#ref</code> #loc may produce <code>java.lang.ClassCastException</code>
|
||||
dataflow.message.arraystore=Storing element of type <code>{0}</code> to array of <code>{1}</code> elements may produce <code>java.lang.ArrayStoreException</code>
|
||||
dataflow.message.redundant.instanceof=Condition <code>#ref</code> #loc is redundant and can be replaced with <code>!= null</code>
|
||||
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 <code>#ref</code> #loc is always <code>{0}</code>
|
||||
dataflow.message.constant.condition.when.reached=Condition <code>#ref</code> #loc is always <code>{0}</code> when reached
|
||||
dataflow.message.loop.on.empty.array=Array <code>#ref</code> is always empty
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<option name="LINE_SEPARATOR" value=" " />
|
||||
<option name="RIGHT_MARGIN" value="140" />
|
||||
<option name="FORMATTER_TAGS_ENABLED" value="true" />
|
||||
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
|
||||
<option name="BLOCK_COMMENT_AT_FIRST_COLUMN" value="false" />
|
||||
<codeStyleSettings language="JAVA">
|
||||
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
|
||||
<option name="BLOCK_COMMENT_AT_FIRST_COLUMN" value="false" />
|
||||
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="WHILE_ON_NEW_LINE" value="true" />
|
||||
<option name="CATCH_ON_NEW_LINE" value="true" />
|
||||
<option name="FINALLY_ON_NEW_LINE" value="true" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
|
||||
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
|
||||
<option name="ALIGN_MULTILINE_ASSIGNMENT" value="true" />
|
||||
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
|
||||
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
|
||||
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
|
||||
<option name="ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION" value="true" />
|
||||
<option name="SPACE_WITHIN_BRACES" value="true" />
|
||||
<option name="SPACE_AFTER_TYPE_CAST" value="false" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="5" />
|
||||
<option name="EXTENDS_LIST_WRAP" value="1" />
|
||||
<option name="THROWS_LIST_WRAP" value="5" />
|
||||
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
|
||||
<option name="THROWS_KEYWORD_WRAP" value="1" />
|
||||
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
|
||||
<option name="BINARY_OPERATION_WRAP" value="5" />
|
||||
<option name="TERNARY_OPERATION_WRAP" value="5" />
|
||||
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
|
||||
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
|
||||
<option name="FOR_STATEMENT_WRAP" value="5" />
|
||||
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
|
||||
<option name="ASSIGNMENT_WRAP" value="1" />
|
||||
<option name="IF_BRACE_FORCE" value="1" />
|
||||
<option name="DOWHILE_BRACE_FORCE" value="1" />
|
||||
<option name="WHILE_BRACE_FORCE" value="1" />
|
||||
<option name="FOR_BRACE_FORCE" value="1" />
|
||||
<option name="FIELD_ANNOTATION_WRAP" value="0" />
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||
<option name="TAB_SIZE" value="8" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<String, String> map) {\n" +
|
||||
" return map /*No class found which is a subtype of both 'Map<String, String>' and 'Date'*/==/**/ date;\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
}
|
||||
|
||||
public void testCommonSubclass() {
|
||||
doTest("import java.util.Date;\n" +
|
||||
"import java.util.Map;\n" +
|
||||
|
||||
@@ -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("]", "|]");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String> 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<String> 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<String> compute() {
|
||||
return Result.create(StringUtil.join(myRegisteredRepositoryIds, ","), new ModificationTracker() {
|
||||
return Result.create(join(myRegisteredRepositoryIds, ","), new ModificationTracker() {
|
||||
@Override
|
||||
public long getModificationCount() {
|
||||
return myRegisteredRepositoryIds.hashCode();
|
||||
|
||||
|
Before Width: | Height: | Size: 232 B After Width: | Height: | Size: 326 B |
|
Before Width: | Height: | Size: 410 B After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 636 B After Width: | Height: | Size: 410 B |
|
Before Width: | Height: | Size: 326 B After Width: | Height: | Size: 232 B |
@@ -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
|
||||
|
||||
@@ -86,7 +86,7 @@ public class RngParser {
|
||||
}
|
||||
};
|
||||
|
||||
private static final ConcurrentMap<String, DPattern> ourCache = ContainerUtil.createConcurrentSoftMap();
|
||||
private static final ConcurrentMap<String, DPattern> 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;
|
||||
}
|
||||
|
||||