Merge remote-tracking branch 'origin/master'

This commit is contained in:
Eugene Zhuravlev
2017-10-25 17:19:11 +02:00
77 changed files with 892 additions and 643 deletions
@@ -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) {
Binary file not shown.

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

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="&#10;" />
<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();
Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 636 B

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

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;
}