mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -60,6 +60,7 @@
|
||||
</options>
|
||||
<keywords keywords="#define;#else;#endif;#error;#if;#ifdef;#ifndef;#include;#line;#undef;auto;bool;break;case;char;const;continue;default;delete;do;double;else;enum;extern;false;float;for;goto;if;int;long;register;return;short;signed;sizeof;static;struct;switch;typedef;union;unsigned;void;volatile;while" ignore_case="false" />
|
||||
<keywords2 keywords="asm;catch;class;const_cast;dynamic_cast;explicit;friend;inline;mutable;namespace;new;operator;private;protected;public;reinterpret_cast;static_cast;this;throw;true;try;typeid;typename;using;virtual;wchar_t" />
|
||||
<keywords3 keywords="->" />
|
||||
</highlighting>
|
||||
</filetype>
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ public class VariablesPanel extends DebuggerTreePanel implements DataProvider {
|
||||
|
||||
@Override
|
||||
protected DebuggerTree createTreeView() {
|
||||
return new FrameVariablesTree(getProject(), SystemProperties.getBooleanProperty("java.debugger.xTree", false) ? this : null);
|
||||
return new FrameVariablesTree(getProject(), SystemProperties.getBooleanProperty("java.debugger.xTree", true) ? this : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -16,8 +16,8 @@
|
||||
package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.util.AtomicNotNullLazyValue;
|
||||
import com.intellij.openapi.util.AtomicNullableLazyValue;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.PsiJavaParserFacadeImpl;
|
||||
@@ -39,18 +39,17 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
|
||||
private final PsiElement myParent;
|
||||
private final String myTypeText;
|
||||
private final char myVariance;
|
||||
private final NotNullLazyValue<Ref<ClsElementImpl>> myChild;
|
||||
private final AtomicNullableLazyValue<ClsElementImpl> myChild;
|
||||
private final NotNullLazyValue<PsiType> myCachedType;
|
||||
|
||||
public ClsTypeElementImpl(@NotNull PsiElement parent, @NotNull String typeText, char variance) {
|
||||
myParent = parent;
|
||||
myTypeText = TypeInfo.internFrequentType(typeText);
|
||||
myVariance = variance;
|
||||
myChild = new AtomicNotNullLazyValue<Ref<ClsElementImpl>>() {
|
||||
@NotNull
|
||||
myChild = new AtomicNullableLazyValue<ClsElementImpl>() {
|
||||
@Override
|
||||
protected Ref<ClsElementImpl> compute() {
|
||||
return Ref.create(calculateChild());
|
||||
protected ClsElementImpl compute() {
|
||||
return calculateChild();
|
||||
}
|
||||
};
|
||||
myCachedType = new AtomicNotNullLazyValue<PsiType>() {
|
||||
@@ -65,7 +64,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
|
||||
@Override
|
||||
@NotNull
|
||||
public PsiElement[] getChildren() {
|
||||
ClsElementImpl child = myChild.getValue().get();
|
||||
ClsElementImpl child = myChild.getValue();
|
||||
return child != null ? new PsiElement[]{child} : PsiElement.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@@ -109,7 +108,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
|
||||
public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException {
|
||||
setMirrorCheckingType(element, JavaElementType.TYPE);
|
||||
|
||||
ClsElementImpl child = myChild.getValue().get();
|
||||
ClsElementImpl child = myChild.getValue();
|
||||
if (child != null) {
|
||||
child.setMirror(element.getFirstChildNode());
|
||||
}
|
||||
@@ -138,24 +137,23 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
|
||||
if (PsiJavaParserFacadeImpl.getPrimitiveType(myTypeText) != null) {
|
||||
return null;
|
||||
}
|
||||
else if (isArray()) {
|
||||
if (isArray()) {
|
||||
return myVariance == VARIANCE_NONE
|
||||
? new ClsTypeElementImpl(this, myTypeText.substring(0, myTypeText.length() - 2), myVariance)
|
||||
: new ClsTypeElementImpl(this, myTypeText, VARIANCE_NONE);
|
||||
}
|
||||
else if (isVarArgs()) {
|
||||
if (isVarArgs()) {
|
||||
return new ClsTypeElementImpl(this, myTypeText.substring(0, myTypeText.length() - 3), myVariance);
|
||||
}
|
||||
else {
|
||||
return myVariance != VARIANCE_INVARIANT ? new ClsJavaCodeReferenceElementImpl(this, myTypeText) : null;
|
||||
}
|
||||
return myVariance == VARIANCE_INVARIANT ? null : new ClsJavaCodeReferenceElementImpl(this, myTypeText);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiType calculateType() {
|
||||
PsiType result = PsiJavaParserFacadeImpl.getPrimitiveType(myTypeText);
|
||||
if (result != null) return result;
|
||||
|
||||
ClsElementImpl childElement = myChild.getValue().get();
|
||||
ClsElementImpl childElement = myChild.getValue();
|
||||
if (childElement instanceof ClsTypeElementImpl) {
|
||||
if (isArray()) {
|
||||
switch (myVariance) {
|
||||
@@ -175,7 +173,7 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
|
||||
return new PsiEllipsisType(((PsiTypeElement)childElement).getType());
|
||||
}
|
||||
}
|
||||
else if (childElement instanceof ClsJavaCodeReferenceElementImpl) {
|
||||
if (childElement instanceof ClsJavaCodeReferenceElementImpl) {
|
||||
PsiClassReferenceType psiClassReferenceType = new PsiClassReferenceType((PsiJavaCodeReferenceElement)childElement, null);
|
||||
switch (myVariance) {
|
||||
case VARIANCE_NONE:
|
||||
@@ -191,10 +189,8 @@ public class ClsTypeElementImpl extends ClsElementImpl implements PsiTypeElement
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert childElement == null : this;
|
||||
return PsiWildcardType.createUnbounded(getManager());
|
||||
}
|
||||
assert childElement == null : this;
|
||||
return PsiWildcardType.createUnbounded(getManager());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -494,20 +494,19 @@ public class PsiClassImpl extends JavaStubPsiElement<PsiClassStub<?>> implements
|
||||
@Override
|
||||
public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) {
|
||||
if (isEnum()) {
|
||||
String name = getName();
|
||||
if (name != null) {
|
||||
String myName = getName();
|
||||
if (myName != null) {
|
||||
try {
|
||||
final NameHint nameHint = processor.getHint(NameHint.KEY);
|
||||
final ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
|
||||
if (nameHint == null || VALUES_METHOD.equals(nameHint.getName(state))) {
|
||||
if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) {
|
||||
if (!processor.execute(getValuesMethod(), ResolveState.initial())) return false;
|
||||
}
|
||||
String nameToSearch = nameHint == null ? null : nameHint.getName(state);
|
||||
if (VALUES_METHOD.equals(nameToSearch) &&
|
||||
(classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD))) {
|
||||
if (!processor.execute(getValuesMethod(), ResolveState.initial())) return false;
|
||||
}
|
||||
if (nameHint == null || VALUE_OF_METHOD.equals(nameHint.getName(state))) {
|
||||
if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD)) {
|
||||
if (!processor.execute(getValueOfMethod(), ResolveState.initial())) return false;
|
||||
}
|
||||
if (VALUE_OF_METHOD.equals(nameToSearch) &&
|
||||
(classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.METHOD))) {
|
||||
if (!processor.execute(getValueOfMethod(), ResolveState.initial())) return false;
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
|
||||
@@ -139,7 +139,7 @@ public class PsiClassReferenceType extends PsiClassType.Stub {
|
||||
public ClassResolveResult resolveGenerics() {
|
||||
PsiUtilCore.ensureValid(myReference);
|
||||
final JavaResolveResult result = myReference.advancedResolve(false);
|
||||
return new DelegatingClassResolveResult(result);
|
||||
return result.getElement() == null ? ClassResolveResult.EMPTY : new DelegatingClassResolveResult(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+9
@@ -189,7 +189,16 @@ class Xoo {
|
||||
class Xoo {
|
||||
}
|
||||
'''
|
||||
}
|
||||
|
||||
public void "test cpp indirection"() {
|
||||
myFixture.configureByText "a.c", '''f<caret>
|
||||
foo->bar
|
||||
'''
|
||||
complete()
|
||||
myFixture.checkResult '''foo<caret>
|
||||
foo->bar
|
||||
'''
|
||||
}
|
||||
|
||||
private void complete() {
|
||||
|
||||
+21
-1
@@ -2,6 +2,9 @@ package com.intellij.remoteServer.impl.runtime.deployment.debug;
|
||||
|
||||
import com.intellij.debugger.DebugEnvironment;
|
||||
import com.intellij.debugger.DebugUIEnvironment;
|
||||
import com.intellij.debugger.DebuggerManager;
|
||||
import com.intellij.debugger.engine.DebugProcess;
|
||||
import com.intellij.debugger.engine.DebugProcessAdapter;
|
||||
import com.intellij.debugger.engine.RemoteDebugProcessHandler;
|
||||
import com.intellij.debugger.ui.DebuggerPanelsManager;
|
||||
import com.intellij.diagnostic.logging.LogFilesManager;
|
||||
@@ -21,6 +24,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.remoteServer.configuration.RemoteServer;
|
||||
import com.intellij.remoteServer.runtime.deployment.debug.JavaDebugConnectionData;
|
||||
import com.intellij.remoteServer.runtime.deployment.debug.JavaDebugServerModeHandler;
|
||||
import com.intellij.remoteServer.runtime.deployment.debug.JavaDebuggerLauncher;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -39,7 +43,9 @@ public class JavaDebuggerLauncherImpl extends JavaDebuggerLauncher {
|
||||
final Project project = executionEnvironment.getProject();
|
||||
Executor executor = DefaultDebugExecutor.getDebugExecutorInstance();
|
||||
final DebuggerPanelsManager manager = DebuggerPanelsManager.getInstance(project);
|
||||
final RemoteConnection remoteConnection = new RemoteConnection(true, info.getHost(), String.valueOf(info.getPort()), false);
|
||||
final JavaDebugServerModeHandler serverModeHandler = info.getServerModeHandler();
|
||||
boolean serverMode = serverModeHandler != null;
|
||||
final RemoteConnection remoteConnection = new RemoteConnection(true, info.getHost(), String.valueOf(info.getPort()), serverMode);
|
||||
DebugEnvironment debugEnvironment = new RemoteServerDebugEnvironment(project, remoteConnection, executionEnvironment.getRunProfile());
|
||||
DebugUIEnvironment debugUIEnvironment = new RemoteServerDebugUIEnvironment(debugEnvironment, executionEnvironment);
|
||||
RunContentDescriptor debugContentDescriptor = manager.attachVirtualMachine(debugUIEnvironment);
|
||||
@@ -49,6 +55,20 @@ public class JavaDebuggerLauncherImpl extends JavaDebuggerLauncher {
|
||||
processHandler.startNotify();
|
||||
ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, debugContentDescriptor,
|
||||
executionEnvironment.getContentToReuse());
|
||||
if (serverMode) {
|
||||
serverModeHandler.attachRemote();
|
||||
DebuggerManager.getInstance(executionEnvironment.getProject())
|
||||
.addDebugProcessListener(processHandler, new DebugProcessAdapter() {
|
||||
public void processDetached(DebugProcess process, boolean closedByUser) {
|
||||
try {
|
||||
serverModeHandler.detachRemote();
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static class RemoteServerDebugUIEnvironment implements DebugUIEnvironment {
|
||||
|
||||
@@ -34,7 +34,10 @@ import com.intellij.execution.process.ProcessOutputTypes;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.sun.jdi.Value;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class DescriptorTestCase extends DebuggerTestCase {
|
||||
private final List<Pair<NodeDescriptorImpl,List<String>>> myDescriptorLog = new ArrayList<Pair<NodeDescriptorImpl, List<String>>>();
|
||||
@@ -51,10 +54,9 @@ public abstract class DescriptorTestCase extends DebuggerTestCase {
|
||||
return getAlternateCollectionRenderer("Map");
|
||||
}
|
||||
|
||||
private NodeRenderer getAlternateCollectionRenderer(final String name) {
|
||||
private static NodeRenderer getAlternateCollectionRenderer(final String name) {
|
||||
final NodeRenderer[] renderers = NodeRendererSettings.getInstance().getAlternateCollectionRenderers();
|
||||
for (int idx = 0; idx < renderers.length; idx++) {
|
||||
NodeRenderer renderer = renderers[idx];
|
||||
for (NodeRenderer renderer : renderers) {
|
||||
if (name.equals(renderer.getName())) {
|
||||
return renderer;
|
||||
}
|
||||
@@ -105,9 +107,8 @@ public abstract class DescriptorTestCase extends DebuggerTestCase {
|
||||
|
||||
private Pair<NodeDescriptorImpl, List<String>> findDescriptorLog(final NodeDescriptorImpl descriptor) {
|
||||
Pair<NodeDescriptorImpl, List<String>> descriptorText = null;
|
||||
for (Iterator<Pair<NodeDescriptorImpl, List<String>>> iterator = myDescriptorLog.iterator(); iterator.hasNext();) {
|
||||
Pair<NodeDescriptorImpl, List<String>> pair = iterator.next();
|
||||
if(pair.getFirst() == descriptor) {
|
||||
for (Pair<NodeDescriptorImpl, List<String>> pair : myDescriptorLog) {
|
||||
if (pair.getFirst() == descriptor) {
|
||||
descriptorText = pair;
|
||||
break;
|
||||
}
|
||||
@@ -115,24 +116,15 @@ public abstract class DescriptorTestCase extends DebuggerTestCase {
|
||||
return descriptorText;
|
||||
}
|
||||
|
||||
protected void flushDescriptor(final NodeDescriptorImpl descriptor) {
|
||||
Pair<NodeDescriptorImpl, List<String>> descriptorLog = findDescriptorLog(descriptor);
|
||||
if(descriptorLog != null) {
|
||||
printDescriptorLog(descriptorLog);
|
||||
myDescriptorLog.remove(descriptorLog);
|
||||
}
|
||||
}
|
||||
|
||||
protected void flushDescriptors() {
|
||||
for (Iterator<Pair<NodeDescriptorImpl, List<String>>> iterator = myDescriptorLog.iterator(); iterator.hasNext();) {
|
||||
printDescriptorLog(iterator.next());
|
||||
for (Pair<NodeDescriptorImpl, List<String>> aMyDescriptorLog : myDescriptorLog) {
|
||||
printDescriptorLog(aMyDescriptorLog);
|
||||
}
|
||||
myDescriptorLog.clear();
|
||||
}
|
||||
|
||||
private void printDescriptorLog(Pair<NodeDescriptorImpl, List<String>> pair) {
|
||||
for (Iterator<String> it = pair.getSecond().iterator(); it.hasNext();) {
|
||||
String text = it.next();
|
||||
for (String text : pair.getSecond()) {
|
||||
print(text, ProcessOutputTypes.SYSTEM);
|
||||
}
|
||||
}
|
||||
@@ -150,6 +142,7 @@ public abstract class DescriptorTestCase extends DebuggerTestCase {
|
||||
String name) {
|
||||
try {
|
||||
StackFrameProxy frameProxy = evaluationContext.getFrameProxy();
|
||||
assert frameProxy != null;
|
||||
LocalVariableDescriptorImpl local = frameTree.getNodeFactory().getLocalVariableDescriptor(null, frameProxy.visibleVariableByName(name));
|
||||
local.setContext(evaluationContext);
|
||||
return local;
|
||||
@@ -169,7 +162,7 @@ public abstract class DescriptorTestCase extends DebuggerTestCase {
|
||||
doExpandAll(tree, runnable, new HashSet<Value>(), null);
|
||||
}
|
||||
|
||||
protected static interface NodeFilter {
|
||||
protected interface NodeFilter {
|
||||
boolean shouldExpand(DebuggerTreeNode node);
|
||||
}
|
||||
|
||||
@@ -186,7 +179,7 @@ public abstract class DescriptorTestCase extends DebuggerTestCase {
|
||||
final DebuggerTreeNode treeNode = (DebuggerTreeNode)tree.getPathForRow(i).getLastPathComponent();
|
||||
if(tree.isCollapsed(i) && !treeNode.isLeaf()) {
|
||||
final NodeDescriptor nodeDescriptor = treeNode.getDescriptor();
|
||||
boolean shouldExpand = filter == null? true : filter.shouldExpand(treeNode);
|
||||
boolean shouldExpand = filter == null || filter.shouldExpand(treeNode);
|
||||
if (shouldExpand) {
|
||||
// additional checks to prevent infinite expand
|
||||
if (nodeDescriptor instanceof ValueDescriptor) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -18,19 +18,22 @@ package com.intellij.openapi.editor.colors;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
||||
/**
|
||||
* A type of item with a distinct highlighting in an editor or in other views.
|
||||
*/
|
||||
public final class TextAttributesKey implements Comparable<TextAttributesKey> {
|
||||
private static final TextAttributes NULL_ATTRIBUTES = new TextAttributes();
|
||||
private static final ConcurrentHashMap<String, TextAttributesKey> ourRegistry = new ConcurrentHashMap<String, TextAttributesKey>();
|
||||
private static final ConcurrentMap<String, TextAttributesKey> ourRegistry = new ConcurrentHashMap<String, TextAttributesKey>();
|
||||
private static final NullableLazyValue<TextAttributeKeyDefaultsProvider> ourDefaultsProvider = new VolatileNullableLazyValue<TextAttributeKeyDefaultsProvider>() {
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -58,7 +61,7 @@ public final class TextAttributesKey implements Comparable<TextAttributesKey> {
|
||||
|
||||
@NotNull
|
||||
public static TextAttributesKey find(@NotNull @NonNls String externalName) {
|
||||
return ourRegistry.cacheOrGet(externalName, new TextAttributesKey(externalName));
|
||||
return ConcurrencyUtil.cacheOrGet(ourRegistry, externalName, new TextAttributesKey(externalName));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -55,7 +55,7 @@ public abstract class DumbService {
|
||||
*/
|
||||
public abstract boolean isDumb();
|
||||
|
||||
public static boolean isDumb(Project project) {
|
||||
public static boolean isDumb(@NotNull Project project) {
|
||||
return getInstance(project).isDumb();
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public abstract class DumbService {
|
||||
* Executes the runnable immediately if not in dumb mode, or on AWT Event Dispatch thread when the dumb mode ends.
|
||||
* @param runnable runnable to run
|
||||
*/
|
||||
public abstract void runWhenSmart(Runnable runnable);
|
||||
public abstract void runWhenSmart(@NotNull Runnable runnable);
|
||||
|
||||
/**
|
||||
* Pause the current thread until dumb mode ends and then continue execution.
|
||||
@@ -75,7 +75,7 @@ public abstract class DumbService {
|
||||
/**
|
||||
* Pause the current thread until dumb mode ends, and then run the read action. Index is guaranteed to be available inside that read action.
|
||||
*/
|
||||
public <T> T runReadActionInSmartMode(final Computable<T> r) {
|
||||
public <T> T runReadActionInSmartMode(@NotNull final Computable<T> r) {
|
||||
final Ref<T> result = new Ref<T>();
|
||||
runReadActionInSmartMode(new Runnable() {
|
||||
@Override
|
||||
@@ -105,7 +105,7 @@ public abstract class DumbService {
|
||||
/**
|
||||
* Pause the current thread until dumb mode ends, and then run the read action. Index is guaranteed to be available inside that read action.
|
||||
*/
|
||||
public void runReadActionInSmartMode(final Runnable r) {
|
||||
public void runReadActionInSmartMode(@NotNull final Runnable r) {
|
||||
while (true) {
|
||||
waitForSmartMode();
|
||||
boolean success = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@@ -130,7 +130,7 @@ public abstract class DumbService {
|
||||
*
|
||||
* @see #runReadActionInSmartMode(Runnable)
|
||||
*/
|
||||
public void repeatUntilPassesInSmartMode(final Runnable r) {
|
||||
public void repeatUntilPassesInSmartMode(@NotNull final Runnable r) {
|
||||
while (true) {
|
||||
waitForSmartMode();
|
||||
try {
|
||||
@@ -156,7 +156,7 @@ public abstract class DumbService {
|
||||
});
|
||||
}
|
||||
|
||||
public void smartInvokeLater(@NotNull final Runnable runnable, ModalityState modalityState) {
|
||||
public void smartInvokeLater(@NotNull final Runnable runnable, @NotNull ModalityState modalityState) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -207,7 +207,7 @@ public abstract class DumbService {
|
||||
});
|
||||
}
|
||||
|
||||
public abstract void showDumbModeNotification(String message);
|
||||
public abstract void showDumbModeNotification(@NotNull String message);
|
||||
|
||||
public abstract Project getProject();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -38,7 +38,7 @@ public class MockDumbService extends DumbService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runWhenSmart(Runnable runnable) {
|
||||
public void runWhenSmart(@NotNull Runnable runnable) {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class MockDumbService extends DumbService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDumbModeNotification(String message) {
|
||||
public void showDumbModeNotification(@NotNull String message) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@@ -58,17 +58,18 @@ public class StubTreeBuilder {
|
||||
final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType();
|
||||
|
||||
PsiFile psi = null;
|
||||
CharSequence contentAsText = null;
|
||||
CharSequence contentAsText = inputData.getContentAsText();
|
||||
Document document = FileDocumentManager.getInstance().getCachedDocument(inputData.getFile());
|
||||
if (document != null) {
|
||||
PsiFile existingPsi = PsiDocumentManager.getInstance(inputData.getProject()).getPsiFile(document);
|
||||
if (existingPsi != null) {
|
||||
contentAsText = existingPsi.getText();
|
||||
psi = existingPsi;
|
||||
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(inputData.getProject());
|
||||
if (psiDocumentManager.isUncommited(document)) {
|
||||
PsiFile existingPsi = psiDocumentManager.getPsiFile(document);
|
||||
if(existingPsi != null) {
|
||||
psi = existingPsi;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (contentAsText == null) {
|
||||
contentAsText = inputData.getContentAsText();
|
||||
if (psi == null) {
|
||||
psi = inputData.getPsiFile();
|
||||
}
|
||||
psi = psi.getViewProvider().getStubBindingRoot();
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ public final class CustomFileTypeLexer extends AbstractCustomLexer {
|
||||
}
|
||||
};
|
||||
|
||||
final IdentifierParser identifierParser = new IdentifierParser();
|
||||
final IdentifierParser identifierParser = new IdentifierParser(parser);
|
||||
|
||||
final QuotedStringParser quotedStringParser = new QuotedStringParser("\"", CustomHighlighterTokenType.STRING, table.isHasStringEscapes());
|
||||
|
||||
|
||||
+8
-5
@@ -23,7 +23,10 @@ import com.intellij.psi.tree.IElementType;
|
||||
* @author dsl
|
||||
*/
|
||||
public class IdentifierParser extends TokenParser {
|
||||
public IdentifierParser() {
|
||||
private final KeywordParser myKeywordParser;
|
||||
|
||||
public IdentifierParser(KeywordParser keywordParser) {
|
||||
myKeywordParser = keywordParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,15 +34,15 @@ public class IdentifierParser extends TokenParser {
|
||||
if (!Character.isJavaIdentifierStart(myBuffer.charAt(position))) return false;
|
||||
final int start = position;
|
||||
for (position++; position < myEndOffset; position++) {
|
||||
final char c = myBuffer.charAt(position);
|
||||
if (!isIdentifierPart(c)) break;
|
||||
if (!isIdentifierPart(position)) break;
|
||||
}
|
||||
IElementType tokenType = CustomHighlighterTokenType.IDENTIFIER;
|
||||
myTokenInfo.updateData(start, position, tokenType);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean isIdentifierPart(final char c) {
|
||||
return Character.isJavaIdentifierPart(c) || c == '-';
|
||||
private boolean isIdentifierPart(int position) {
|
||||
if (myBuffer.charAt(position) == '-') return !myKeywordParser.hasToken(position, myBuffer, null);
|
||||
return KeywordParser.isWordPart(position, myBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-10
@@ -23,6 +23,7 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.util.containers.CharTrie;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -63,10 +64,9 @@ public class KeywordParser {
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean hasToken(int position, CharSequence myBuffer, TokenInfo myTokenInfo) {
|
||||
public boolean hasToken(int position, CharSequence myBuffer, @Nullable TokenInfo tokenInfo) {
|
||||
int index = 0;
|
||||
int offset = position;
|
||||
boolean found = false;
|
||||
while (offset < myBuffer.length()) {
|
||||
char c = myBuffer.charAt(offset++);
|
||||
int nextIndex = myTrie.findSubNode(index, myIgnoreCase ? Character.toUpperCase(c) : c);
|
||||
@@ -79,24 +79,29 @@ public class KeywordParser {
|
||||
String testKeyword = myIgnoreCase ? StringUtil.toUpperCase(keyword) : keyword;
|
||||
for (int i = 0; i < CustomHighlighterTokenType.KEYWORD_TYPE_COUNT; i++) {
|
||||
if (myKeywordSets.get(i).contains(testKeyword)) {
|
||||
myTokenInfo.updateData(position, position + keyword.length(), getToken(i));
|
||||
found = true;
|
||||
break;
|
||||
if (tokenInfo != null) {
|
||||
tokenInfo.updateData(position, position + keyword.length(), getToken(i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isWordEnd(int offset, CharSequence myBuffer) {
|
||||
if (offset == myBuffer.length()) {
|
||||
private static boolean isWordEnd(int offset, CharSequence sequence) {
|
||||
if (offset == sequence.length()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !isWordPart(offset - 1, sequence) || !isWordPart(offset, sequence);
|
||||
}
|
||||
|
||||
char ch = myBuffer.charAt(offset);
|
||||
return ch != '-' && ch != '_' && !Character.isLetterOrDigit(ch);
|
||||
static boolean isWordPart(int offset, CharSequence sequence) {
|
||||
char ch = sequence.charAt(offset);
|
||||
return ch == '-' || Character.isJavaIdentifierPart(ch);
|
||||
}
|
||||
|
||||
private static IElementType getToken(int keywordSetIndex) {
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -40,7 +40,7 @@ public class CompositeFilterTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runWhenSmart(Runnable runnable) {
|
||||
public void runWhenSmart(@NotNull Runnable runnable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,7 +53,7 @@ public class CompositeFilterTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDumbModeNotification(String message) {
|
||||
public void showDumbModeNotification(@NotNull String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+212
-208
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -30,7 +30,6 @@ import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.ListPopupStep;
|
||||
@@ -53,7 +52,7 @@ import java.awt.event.MouseEvent;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
class ChooseRunConfigurationPopup implements ExecutorProvider {
|
||||
public class ChooseRunConfigurationPopup implements ExecutorProvider {
|
||||
|
||||
private final Project myProject;
|
||||
@NotNull private final String myAddKey;
|
||||
@@ -304,7 +303,7 @@ class ChooseRunConfigurationPopup implements ExecutorProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class ItemWrapper<T> extends Wrapper {
|
||||
public abstract static class ItemWrapper<T> extends Wrapper {
|
||||
private final T myValue;
|
||||
private boolean myDynamic;
|
||||
|
||||
@@ -430,7 +429,7 @@ class ChooseRunConfigurationPopup implements ExecutorProvider {
|
||||
@NotNull final Project project,
|
||||
@NotNull final ExecutorProvider executorProvider,
|
||||
@NotNull final String title) {
|
||||
super(title, createSettingsList(project, executorProvider));
|
||||
super(title, createSettingsList(project, executorProvider, true));
|
||||
myProject = project;
|
||||
myAction = action;
|
||||
|
||||
@@ -456,209 +455,6 @@ class ChooseRunConfigurationPopup implements ExecutorProvider {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static ItemWrapper[] createSettingsList(@NotNull final Project project, @NotNull ExecutorProvider executorProvider) {
|
||||
final RunManagerEx manager = RunManagerEx.getInstanceEx(project);
|
||||
|
||||
final List<ItemWrapper> result = new ArrayList<ItemWrapper>();
|
||||
|
||||
final RunnerAndConfigurationSettings selectedConfiguration = manager.getSelectedConfiguration();
|
||||
|
||||
if (selectedConfiguration != null) {
|
||||
boolean isFirst = true;
|
||||
final ExecutionTarget activeTarget = ExecutionTargetManager.getActiveTarget(project);
|
||||
for (final ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, selectedConfiguration)) {
|
||||
result.add(new ItemWrapper<ExecutionTarget>(eachTarget, isFirst) {
|
||||
{
|
||||
setChecked(eachTarget.equals(activeTarget));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return eachTarget.getIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return eachTarget.getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) {
|
||||
ExecutionTargetManager.setActiveTarget(project, eachTarget);
|
||||
doRunConfiguration(selectedConfiguration, executor, project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean available(Executor executor) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
isFirst = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final Map<RunnerAndConfigurationSettings, ItemWrapper> wrappedExisting = new LinkedHashMap<RunnerAndConfigurationSettings, ItemWrapper>();
|
||||
final ConfigurationType[] types = manager.getConfigurationFactories();
|
||||
for (final ConfigurationType type : types) {
|
||||
if (!(type instanceof UnknownConfigurationType)) {
|
||||
Map<String, List<RunnerAndConfigurationSettings>> structure = manager.getStructure(type);
|
||||
for (final Map.Entry<String, List<RunnerAndConfigurationSettings>> entry : structure.entrySet()) {
|
||||
if (entry.getValue().isEmpty())
|
||||
continue;
|
||||
final String key = entry.getKey();
|
||||
if (key != null){
|
||||
boolean isSelected = entry.getValue().contains(selectedConfiguration);
|
||||
FolderWrapper folderWrapper = new FolderWrapper(project, executorProvider, key + (isSelected ? " (mnemonic is to \"" + selectedConfiguration.getName()+"\")" : ""), entry.getValue());
|
||||
if (isSelected) {
|
||||
folderWrapper.setMnemonic(1);
|
||||
}
|
||||
result.add(folderWrapper);
|
||||
}
|
||||
else {
|
||||
for (RunnerAndConfigurationSettings configuration : entry.getValue()) {
|
||||
final ItemWrapper wrapped = ItemWrapper.wrap(project, configuration);
|
||||
if (configuration == selectedConfiguration) {
|
||||
wrapped.setMnemonic(1);
|
||||
}
|
||||
wrappedExisting.put(configuration, wrapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
populateWithDynamicRunners(result, wrappedExisting, project, manager, selectedConfiguration);
|
||||
result.addAll(wrappedExisting.values());
|
||||
|
||||
//noinspection unchecked
|
||||
final ItemWrapper edit = new ItemWrapper(null) {
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return AllIcons.Actions.EditSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return UIUtil.removeMnemonic(ActionsBundle.message("action.editRunConfigurations.text"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) {
|
||||
final EditConfigurationsDialog dialog = new EditConfigurationsDialog(project) {
|
||||
@Override
|
||||
protected void init() {
|
||||
setOKButtonText(executor.getStartActionText());
|
||||
setOKButtonIcon(executor.getIcon());
|
||||
myExecutor = executor;
|
||||
super.init();
|
||||
}
|
||||
};
|
||||
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doRunConfiguration(RunManager.getInstance(project).getSelectedConfiguration(), executor, project);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean available(Executor executor) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
edit.setMnemonic(0);
|
||||
result.add(0, edit);
|
||||
|
||||
return result.toArray(new ItemWrapper[result.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<RunnerAndConfigurationSettings> populateWithDynamicRunners(final List<ItemWrapper> result,
|
||||
Map<RunnerAndConfigurationSettings, ItemWrapper> existing,
|
||||
final Project project, final RunManagerEx manager,
|
||||
final RunnerAndConfigurationSettings selectedConfiguration) {
|
||||
|
||||
final ArrayList<RunnerAndConfigurationSettings> contextConfigurations = new ArrayList<RunnerAndConfigurationSettings>();
|
||||
final DataContext dataContext = DataManager.getInstance().getDataContext();
|
||||
final ConfigurationContext context = ConfigurationContext.getFromContext(dataContext);
|
||||
|
||||
final List<ConfigurationFromContext> producers = PreferredProducerFind.getConfigurationsFromContext(context.getLocation(),
|
||||
context, false);
|
||||
if (producers == null) return Collections.emptyList();
|
||||
|
||||
Collections.sort(producers, ConfigurationFromContext.NAME_COMPARATOR);
|
||||
|
||||
final RunnerAndConfigurationSettings[] preferred = {null};
|
||||
|
||||
int i = 2; // selectedConfiguration == null ? 1 : 2;
|
||||
for (final ConfigurationFromContext fromContext : producers) {
|
||||
final RunnerAndConfigurationSettings configuration = fromContext.getConfigurationSettings();
|
||||
if (existing.keySet().contains(configuration)) {
|
||||
final ItemWrapper wrapper = existing.get(configuration);
|
||||
if (wrapper.getMnemonic() != 1) {
|
||||
wrapper.setMnemonic(i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (selectedConfiguration != null && configuration.equals(selectedConfiguration)) continue;
|
||||
contextConfigurations.add(configuration);
|
||||
|
||||
if (preferred[0] == null) {
|
||||
preferred[0] = configuration;
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
final ItemWrapper wrapper = new ItemWrapper(configuration) {
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return RunManagerEx.getInstanceEx(project).getConfigurationIcon(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return configuration.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean available(Executor executor) {
|
||||
return canRun(executor, configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) {
|
||||
manager.setTemporaryConfiguration(configuration);
|
||||
RunManagerEx.getInstanceEx(project).setSelectedConfiguration(configuration);
|
||||
doRunConfiguration(configuration, executor, project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupStep getNextStep(@NotNull final Project project, @NotNull final ChooseRunConfigurationPopup action) {
|
||||
return new ConfigurationActionsStep(project, action, configuration, isDynamic());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActions() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
wrapper.setDynamic(true);
|
||||
wrapper.setMnemonic(i);
|
||||
result.add(wrapper);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return contextConfigurations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListSeparator getSeparatorAbove(ItemWrapper value) {
|
||||
if (value.addSeparatorAbove()) return new ListSeparator();
|
||||
@@ -1135,4 +931,212 @@ class ChooseRunConfigurationPopup implements ExecutorProvider {
|
||||
return !selectedValue.getValues().isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public static ItemWrapper[] createSettingsList(@NotNull final Project project, @NotNull ExecutorProvider executorProvider, boolean createEditAction) {
|
||||
final RunManagerEx manager = RunManagerEx.getInstanceEx(project);
|
||||
|
||||
final List<ItemWrapper> result = new ArrayList<ItemWrapper>();
|
||||
|
||||
final RunnerAndConfigurationSettings selectedConfiguration = manager.getSelectedConfiguration();
|
||||
|
||||
if (selectedConfiguration != null) {
|
||||
boolean isFirst = true;
|
||||
final ExecutionTarget activeTarget = ExecutionTargetManager.getActiveTarget(project);
|
||||
for (final ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, selectedConfiguration)) {
|
||||
result.add(new ItemWrapper<ExecutionTarget>(eachTarget, isFirst) {
|
||||
{
|
||||
setChecked(eachTarget.equals(activeTarget));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return eachTarget.getIcon();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return eachTarget.getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) {
|
||||
ExecutionTargetManager.setActiveTarget(project, eachTarget);
|
||||
doRunConfiguration(selectedConfiguration, executor, project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean available(Executor executor) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
isFirst = false;
|
||||
}
|
||||
}
|
||||
|
||||
final Map<RunnerAndConfigurationSettings, ItemWrapper> wrappedExisting = new LinkedHashMap<RunnerAndConfigurationSettings, ItemWrapper>();
|
||||
final ConfigurationType[] types = manager.getConfigurationFactories();
|
||||
for (final ConfigurationType type : types) {
|
||||
if (!(type instanceof UnknownConfigurationType)) {
|
||||
Map<String, List<RunnerAndConfigurationSettings>> structure = manager.getStructure(type);
|
||||
for (final Map.Entry<String, List<RunnerAndConfigurationSettings>> entry : structure.entrySet()) {
|
||||
if (entry.getValue().isEmpty())
|
||||
continue;
|
||||
final String key = entry.getKey();
|
||||
if (key != null){
|
||||
boolean isSelected = entry.getValue().contains(selectedConfiguration);
|
||||
FolderWrapper folderWrapper = new FolderWrapper(project, executorProvider, key + (isSelected ? " (mnemonic is to \"" + selectedConfiguration.getName()+"\")" : ""), entry.getValue());
|
||||
if (isSelected) {
|
||||
folderWrapper.setMnemonic(1);
|
||||
}
|
||||
result.add(folderWrapper);
|
||||
}
|
||||
else {
|
||||
for (RunnerAndConfigurationSettings configuration : entry.getValue()) {
|
||||
final ItemWrapper wrapped = ItemWrapper.wrap(project, configuration);
|
||||
if (configuration == selectedConfiguration) {
|
||||
wrapped.setMnemonic(1);
|
||||
}
|
||||
wrappedExisting.put(configuration, wrapped);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
populateWithDynamicRunners(result, wrappedExisting, project, manager, selectedConfiguration);
|
||||
result.addAll(wrappedExisting.values());
|
||||
|
||||
//noinspection unchecked
|
||||
final ItemWrapper edit = new ItemWrapper(null) {
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return AllIcons.Actions.EditSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return UIUtil.removeMnemonic(ActionsBundle.message("action.editRunConfigurations.text"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(@NotNull final Project project, @NotNull final Executor executor, @NotNull DataContext context) {
|
||||
final EditConfigurationsDialog dialog = new EditConfigurationsDialog(project) {
|
||||
@Override
|
||||
protected void init() {
|
||||
setOKButtonText(executor.getStartActionText());
|
||||
setOKButtonIcon(executor.getIcon());
|
||||
myExecutor = executor;
|
||||
super.init();
|
||||
}
|
||||
};
|
||||
|
||||
dialog.show();
|
||||
if (dialog.isOK()) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doRunConfiguration(RunManager.getInstance(project).getSelectedConfiguration(), executor, project);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean available(Executor executor) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
edit.setMnemonic(0);
|
||||
if (createEditAction) {
|
||||
result.add(0, edit);
|
||||
}
|
||||
|
||||
return result.toArray(new ItemWrapper[result.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<RunnerAndConfigurationSettings> populateWithDynamicRunners(final List<ItemWrapper> result,
|
||||
Map<RunnerAndConfigurationSettings, ItemWrapper> existing,
|
||||
final Project project, final RunManagerEx manager,
|
||||
final RunnerAndConfigurationSettings selectedConfiguration) {
|
||||
|
||||
final ArrayList<RunnerAndConfigurationSettings> contextConfigurations = new ArrayList<RunnerAndConfigurationSettings>();
|
||||
if (!EventQueue.isDispatchThread()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final DataContext dataContext = DataManager.getInstance().getDataContext();
|
||||
final ConfigurationContext context = ConfigurationContext.getFromContext(dataContext);
|
||||
|
||||
final List<ConfigurationFromContext> producers = PreferredProducerFind.getConfigurationsFromContext(context.getLocation(),
|
||||
context, false);
|
||||
if (producers == null) return Collections.emptyList();
|
||||
|
||||
Collections.sort(producers, ConfigurationFromContext.NAME_COMPARATOR);
|
||||
|
||||
final RunnerAndConfigurationSettings[] preferred = {null};
|
||||
|
||||
int i = 2; // selectedConfiguration == null ? 1 : 2;
|
||||
for (final ConfigurationFromContext fromContext : producers) {
|
||||
final RunnerAndConfigurationSettings configuration = fromContext.getConfigurationSettings();
|
||||
if (existing.keySet().contains(configuration)) {
|
||||
final ItemWrapper wrapper = existing.get(configuration);
|
||||
if (wrapper.getMnemonic() != 1) {
|
||||
wrapper.setMnemonic(i);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (selectedConfiguration != null && configuration.equals(selectedConfiguration)) continue;
|
||||
contextConfigurations.add(configuration);
|
||||
|
||||
if (preferred[0] == null) {
|
||||
preferred[0] = configuration;
|
||||
}
|
||||
|
||||
//noinspection unchecked
|
||||
final ItemWrapper wrapper = new ItemWrapper(configuration) {
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return RunManagerEx.getInstanceEx(project).getConfigurationIcon(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return configuration.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean available(Executor executor) {
|
||||
return canRun(executor, configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void perform(@NotNull Project project, @NotNull Executor executor, @NotNull DataContext context) {
|
||||
manager.setTemporaryConfiguration(configuration);
|
||||
RunManagerEx.getInstanceEx(project).setSelectedConfiguration(configuration);
|
||||
doRunConfiguration(configuration, executor, project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupStep getNextStep(@NotNull final Project project, @NotNull final ChooseRunConfigurationPopup action) {
|
||||
return new ConfigurationActionsStep(project, action, configuration, isDynamic());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActions() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
wrapper.setDynamic(true);
|
||||
wrapper.setMnemonic(i);
|
||||
result.add(wrapper);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return contextConfigurations;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -20,6 +20,6 @@ import com.intellij.execution.Executor;
|
||||
/**
|
||||
* User: Vassiliy.Kudryashov
|
||||
*/
|
||||
interface ExecutorProvider {
|
||||
public interface ExecutorProvider {
|
||||
Executor getExecutor();
|
||||
}
|
||||
|
||||
+5
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -198,25 +198,6 @@ public class RunConfigurationsComboBoxAction extends ComboBoxAction implements D
|
||||
}
|
||||
}
|
||||
|
||||
//final RunnerAndConfigurationSettings[] configurations = runManager.getConfigurationSettingsList(type);
|
||||
//ArrayList<RunnerAndConfigurationSettings> configurationSettingsList = new ArrayList<RunnerAndConfigurationSettings>();
|
||||
//int i = 0;
|
||||
//for (RunnerAndConfigurationSettings configuration : configurations) {
|
||||
// if (configuration.isTemporary()) {
|
||||
// configurationSettingsList.add(configuration);
|
||||
// }
|
||||
// else {
|
||||
// configurationSettingsList.add(i++, configuration);
|
||||
// }
|
||||
//}
|
||||
//for (final RunnerAndConfigurationSettings configuration : configurationSettingsList) {
|
||||
// //if (runManager.canRunConfiguration(configuration)) {
|
||||
// final SelectConfigAction action = new SelectConfigAction(configuration, project);
|
||||
//
|
||||
// actionGroup.add(action);
|
||||
// //}
|
||||
//}
|
||||
|
||||
allActionsGroup.add(actionGroup);
|
||||
allActionsGroup.addSeparator();
|
||||
}
|
||||
@@ -319,7 +300,10 @@ public class RunConfigurationsComboBoxAction extends ComboBoxAction implements D
|
||||
}
|
||||
final Presentation presentation = getTemplatePresentation();
|
||||
presentation.setText(name, false);
|
||||
presentation.setDescription("Select " + configuration.getType().getConfigurationTypeDescription() + " '" + name + "'");
|
||||
final ConfigurationType type = configuration.getType();
|
||||
if (type != null) {
|
||||
presentation.setDescription("Select " + type.getConfigurationTypeDescription() + " '" + name + "'");
|
||||
}
|
||||
updateIcon(presentation);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
package com.intellij.ide.actions;
|
||||
|
||||
import com.intellij.codeInsight.navigation.NavigationUtil;
|
||||
import com.intellij.execution.Executor;
|
||||
import com.intellij.execution.ExecutorRegistry;
|
||||
import com.intellij.execution.actions.ChooseRunConfigurationPopup;
|
||||
import com.intellij.execution.actions.ExecutorProvider;
|
||||
import com.intellij.execution.executors.DefaultRunExecutor;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.DataManager;
|
||||
@@ -66,6 +71,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.VirtualFilePathWrapper;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.impl.IdeFrameImpl;
|
||||
@@ -115,6 +121,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
public static final int SEARCH_FIELD_COLUMNS = 25;
|
||||
private static final int MAX_CLASSES = 6;
|
||||
private static final int MAX_FILES = 6;
|
||||
private static final int MAX_RUN_CONFIGURATION = 6;
|
||||
private static final int MAX_TOOL_WINDOWS = 4;
|
||||
private static final int MAX_SYMBOLS = 6;
|
||||
private static final int MAX_SETTINGS = 5;
|
||||
@@ -149,6 +156,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
private AnActionEvent myActionEvent;
|
||||
private Component myContextComponent;
|
||||
private CalcThread myCalcThread;
|
||||
private static AtomicBoolean ourShiftIsPressed = new AtomicBoolean(false);
|
||||
private static AtomicBoolean shift1Pressed = new AtomicBoolean(false);
|
||||
private static AtomicBoolean shift1Released = new AtomicBoolean(false);
|
||||
private static AtomicBoolean shift2Pressed = new AtomicBoolean(false);
|
||||
@@ -170,6 +178,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
final int keyCode = keyEvent.getKeyCode();
|
||||
|
||||
if (keyCode == KeyEvent.VK_SHIFT) {
|
||||
ourShiftIsPressed.set(event.getID() == KeyEvent.KEY_PRESSED);
|
||||
|
||||
if (keyEvent.isControlDown() || keyEvent.isAltDown() || keyEvent.isMetaDown()) {
|
||||
resetState();
|
||||
return false;
|
||||
@@ -521,7 +531,9 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
|
||||
private void doNavigate(int index) {
|
||||
final Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(getField().getTextEditor()));
|
||||
|
||||
final Executor executor = ourShiftIsPressed.get()
|
||||
? DefaultRunExecutor.getRunExecutorInstance()
|
||||
: ExecutorRegistry.getInstance().getExecutorById(ToolWindowId.DEBUG);
|
||||
assert project != null;
|
||||
|
||||
if (isMoreItem(index)) {
|
||||
@@ -569,7 +581,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (isActionValue(value) || isSetting(value)) {
|
||||
else if (isActionValue(value) || isSetting(value) || isRunConfiguration(value)) {
|
||||
focusManager.requestDefaultFocus(true);
|
||||
final Component comp = myContextComponent;
|
||||
final AnActionEvent event = myActionEvent;
|
||||
@@ -580,7 +592,12 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
if (c == null) {
|
||||
c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
}
|
||||
GotoActionAction.openOptionOrPerformAction(value, pattern, project, c, event);
|
||||
|
||||
if (isRunConfiguration(value)) {
|
||||
((ChooseRunConfigurationPopup.ItemWrapper)value).perform(project, executor, DataManager.getInstance().getDataContext(c));
|
||||
} else {
|
||||
GotoActionAction.openOptionOrPerformAction(value, pattern, project, c, event);
|
||||
}
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -665,6 +682,20 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
myHistoryIndex = 0;
|
||||
myHistoryItem = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||
myList.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_SHIFT) {
|
||||
myList.repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
initSearchField(myPopupField);
|
||||
myPopupField.setOpaque(false);
|
||||
@@ -817,7 +848,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
doNavigate(index);
|
||||
}
|
||||
}
|
||||
}.registerCustomShortcutSet(CustomShortcutSet.fromString("ENTER"), editor, balloon);
|
||||
}.registerCustomShortcutSet(CustomShortcutSet.fromString("ENTER", "shift ENTER"), editor, balloon);
|
||||
new DumbAwareAction(){
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
@@ -922,7 +953,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
&& myProject != null
|
||||
&& (((VirtualFile)value).isDirectory()
|
||||
|| (file = PsiManager.getInstance(myProject).findFile((VirtualFile)value)) != null)) {
|
||||
cmp = new GotoFileCellRenderer(Math.min(800, list.getWidth())).getListCellRendererComponent(list, file == null ? value : file, index, isSelected, cellHasFocus);
|
||||
cmp = new GotoFileCellRenderer(Math.min(800, list.getWidth()))
|
||||
.getListCellRendererComponent(list, file == null ? value : file, index, isSelected, cellHasFocus);
|
||||
} else if (value instanceof PsiElement) {
|
||||
cmp = myPsiRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
} else {
|
||||
@@ -979,8 +1011,13 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
String name = myClassModel.getElementName(value);
|
||||
assert name != null;
|
||||
append(name);
|
||||
}
|
||||
else if (isVirtualFile(value)) {
|
||||
} else if (value instanceof ChooseRunConfigurationPopup.ItemWrapper) {
|
||||
final ChooseRunConfigurationPopup.ItemWrapper wrapper = (ChooseRunConfigurationPopup.ItemWrapper)value;
|
||||
append(wrapper.getText());
|
||||
setIcon(wrapper.getIcon());
|
||||
setLocationString(ourShiftIsPressed.get() ? "Run" : "Debug");
|
||||
myLocationIcon = ourShiftIsPressed.get() ? AllIcons.Toolwindows.ToolWindowRun : AllIcons.Toolwindows.ToolWindowDebugger;
|
||||
} else if (isVirtualFile(value)) {
|
||||
final VirtualFile file = (VirtualFile)value;
|
||||
if (file instanceof VirtualFilePathWrapper) {
|
||||
append(((VirtualFilePathWrapper)file).getPresentablePath());
|
||||
@@ -1102,6 +1139,10 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
return o instanceof OptionDescription;
|
||||
}
|
||||
|
||||
private static boolean isRunConfiguration(Object o) {
|
||||
return o instanceof ChooseRunConfigurationPopup.ItemWrapper;
|
||||
}
|
||||
|
||||
private static boolean isVirtualFile(Object o) {
|
||||
return o instanceof VirtualFile;
|
||||
}
|
||||
@@ -1148,12 +1189,23 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
return;
|
||||
}
|
||||
|
||||
checkModelsUpToDate(); check();
|
||||
buildTopHit(pattern); check();
|
||||
buildRecentFiles(pattern); check();
|
||||
updatePopup(); check();
|
||||
buildToolWindows(pattern); check();
|
||||
updatePopup(); check();
|
||||
checkModelsUpToDate(); check();
|
||||
buildTopHit(pattern); check();
|
||||
buildRecentFiles(pattern); check();
|
||||
updatePopup(); check();
|
||||
buildToolWindows(pattern); check();
|
||||
updatePopup(); check();
|
||||
|
||||
if (!DumbServiceImpl.getInstance(project).isDumb()) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
buildRunConfigurations(pattern);
|
||||
}
|
||||
});
|
||||
|
||||
updatePopup();
|
||||
check();
|
||||
}
|
||||
|
||||
if (!DumbServiceImpl.getInstance(project).isDumb()) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@@ -1387,6 +1439,86 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
}
|
||||
|
||||
private void buildRunConfigurations(String pattern) {
|
||||
final List<Object> runConfigurations = new ArrayList<Object>();
|
||||
MinusculeMatcher matcher = new MinusculeMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE);
|
||||
final ChooseRunConfigurationPopup.ItemWrapper[] wrappers =
|
||||
ChooseRunConfigurationPopup.createSettingsList(project, new ExecutorProvider() {
|
||||
@Override
|
||||
public Executor getExecutor() {
|
||||
return ExecutorRegistry.getInstance().getExecutorById(ToolWindowId.DEBUG);
|
||||
}
|
||||
}, false);
|
||||
check();
|
||||
for (ChooseRunConfigurationPopup.ItemWrapper wrapper : wrappers) {
|
||||
if (matcher.matches(wrapper.getText())) {
|
||||
runConfigurations.add(wrapper);
|
||||
}
|
||||
check();
|
||||
}
|
||||
|
||||
if (runConfigurations.size() > 0) {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myProgressIndicator.isCanceled()) {
|
||||
myTitleIndexes.runConfigurations = myListModel.size();
|
||||
for (Object runConfiguration : runConfigurations) {
|
||||
myListModel.addElement(runConfiguration);
|
||||
}
|
||||
myMoreFilesIndex = runConfigurations.size() >= MAX_RUN_CONFIGURATION ? myListModel.size() - 1 : -1;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//private void buildRunConfigurations(String pattern) {
|
||||
// MinusculeMatcher matcher = new MinusculeMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE);
|
||||
// RunnerAndConfigurationSettings selected = RunManager.getInstance(project).getSelectedConfiguration();
|
||||
// final List<Object> runConfigurations = new ArrayList<Object>();
|
||||
// final RunManagerEx runManager = RunManagerEx.getInstanceEx(project);
|
||||
// if (selected != null) {
|
||||
// ExecutionTarget activeTarget = ExecutionTargetManager.getActiveTarget(project);
|
||||
// for (ExecutionTarget eachTarget : ExecutionTargetManager.getTargetsToChooseFor(project, selected)) {
|
||||
// if (matcher.matches(eachTarget.getDisplayName())) {
|
||||
// runConfigurations.add(
|
||||
// new RunConfigurationsComboBoxAction.SelectTargetAction(project, eachTarget, eachTarget.equals(activeTarget)));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// final ConfigurationType[] types = runManager.getConfigurationFactories();
|
||||
// for (ConfigurationType type : types) {
|
||||
// Map<String, List<RunnerAndConfigurationSettings>> structure = runManager.getStructure(type);
|
||||
// for (Map.Entry<String, List<RunnerAndConfigurationSettings>> entry : structure.entrySet()) {
|
||||
// for (RunnerAndConfigurationSettings settings : entry.getValue()) {
|
||||
// if (matcher.matches(settings.getName())) {
|
||||
// runConfigurations.add(new RunConfigurationsComboBoxAction.SelectConfigAction(settings, project));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (runConfigurations.size() > 0) {
|
||||
// UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// if (!myProgressIndicator.isCanceled()) {
|
||||
// myTitleIndexes.runConfigurations = myListModel.size();
|
||||
// for (Object runConfiguration : runConfigurations) {
|
||||
// myListModel.addElement(runConfiguration);
|
||||
// }
|
||||
// myMoreFilesIndex = runConfigurations.size() >= MAX_RUN_CONFIGURATION ? myListModel.size() - 1 : -1;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
private void buildClasses(String pattern, boolean includeLibraries) {
|
||||
if (pattern.indexOf('.') != -1) {
|
||||
//todo[kb] it's not a mistake. If we search for "*.png" or "index.xml" in SearchEverywhere
|
||||
@@ -1402,6 +1534,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
List<MatchResult> matches = collectResults(pattern, includeLibs ? myClassModel.getNames(true) : myClasses, myClassModel);
|
||||
// FindSymbolParameters parameters = FindSymbolParameters.wrap(pattern, project, includeLibs);
|
||||
final List<Object> classes = new ArrayList<Object>();
|
||||
check();
|
||||
|
||||
for (MatchResult matchResult : matches) {
|
||||
if (clsCounter > maxCount) break;
|
||||
@@ -1507,6 +1640,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
myAlreadyAddedActions.add(action);
|
||||
}
|
||||
break;
|
||||
case RUN_CONFIGURATION:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1828,6 +1963,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
static class TitleIndexes {
|
||||
int topHit;
|
||||
int recentFiles;
|
||||
int runConfigurations;
|
||||
int classes;
|
||||
int files;
|
||||
int actions;
|
||||
@@ -1840,6 +1976,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
final String gotoActionTitle;
|
||||
final String gotoSettingsTitle;
|
||||
final String gotoRecentFilesTitle;
|
||||
final String gotoRunConfigurationsTitle;
|
||||
final String gotoSymbolTitle;
|
||||
static final String toolWindowsTitle = "Tool Windows";
|
||||
|
||||
@@ -1855,12 +1992,18 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
String gotoRecentFiles = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("RecentFiles"));
|
||||
gotoRecentFilesTitle = StringUtil.isEmpty(gotoRecentFiles) ? "Recent Files" : "Recent Files (" + gotoRecentFiles + ")";
|
||||
String gotoSymbol = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("GotoSymbol"));
|
||||
gotoSymbolTitle = StringUtil.isEmpty(gotoClass) ? "Symbols" : "Symbols (" + gotoSymbol + ")";
|
||||
gotoSymbolTitle = StringUtil.isEmpty(gotoSymbol) ? "Symbols" : "Symbols (" + gotoSymbol + ")";
|
||||
String gotoRunConfiguration = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ChooseDebugConfiguration"));
|
||||
if (StringUtil.isEmpty(gotoRunConfiguration)) {
|
||||
gotoRunConfiguration = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction("ChooseRunConfiguration"));
|
||||
}
|
||||
gotoRunConfigurationsTitle = StringUtil.isEmpty(gotoRunConfiguration) ? "Run Configurations" : "Run Configurations (" + gotoRunConfiguration + ")";
|
||||
}
|
||||
|
||||
String getTitle(int index) {
|
||||
if (index == topHit) return index == 0 ? "Top Hit" : "Top Hits";
|
||||
if (index == recentFiles) return gotoRecentFilesTitle;
|
||||
if (index == runConfigurations) return gotoRunConfigurationsTitle;
|
||||
if (index == classes) return gotoClassTitle;
|
||||
if (index == files) return gotoFileTitle;
|
||||
if (index == toolWindows) return toolWindowsTitle;
|
||||
@@ -1871,7 +2014,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
|
||||
int next(int index) {
|
||||
int[] all = new int[]{topHit, recentFiles, classes, files, actions, settings, toolWindows, symbols};
|
||||
int[] all = new int[]{topHit, recentFiles, runConfigurations, classes, files, actions, settings, toolWindows, symbols};
|
||||
Arrays.sort(all);
|
||||
for (int next : all) {
|
||||
if (next > index) return next;
|
||||
@@ -1880,7 +2023,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
|
||||
int prev(int index) {
|
||||
int[] all = new int[]{topHit, recentFiles, classes, files, actions, settings, toolWindows, symbols};
|
||||
int[] all = new int[]{topHit, recentFiles, runConfigurations, classes, files, actions, settings, toolWindows, symbols};
|
||||
Arrays.sort(all);
|
||||
for (int i = all.length-1; i >= 0; i--) {
|
||||
if (all[i] != -1 && all[i] < index) return all[i];
|
||||
@@ -1891,6 +2034,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
|
||||
public void clear() {
|
||||
topHit = -1;
|
||||
runConfigurations = -1;
|
||||
recentFiles = -1;
|
||||
classes = -1;
|
||||
files = -1;
|
||||
@@ -1960,7 +2104,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
return result;
|
||||
}
|
||||
|
||||
private enum HistoryType {CLASS, FILE, SYMBOL, SETTING, ACTION}
|
||||
private enum HistoryType {CLASS, FILE, SYMBOL, SETTING, ACTION, RUN_CONFIGURATION}
|
||||
|
||||
@Nullable
|
||||
private static HistoryType parseHistoryType(@Nullable String name) {
|
||||
|
||||
@@ -1420,7 +1420,11 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
return; // no need to index unsaved docs
|
||||
}
|
||||
|
||||
Set<Document> documents = myPsiDependentIndices.contains(indexId) ? getTransactedDocuments() : getUnsavedDocuments();
|
||||
Set<Document> documents = getUnsavedDocuments();
|
||||
boolean psiBasedIndex = myPsiDependentIndices.contains(indexId);
|
||||
if(psiBasedIndex) {
|
||||
documents.addAll(getTransactedDocuments());
|
||||
}
|
||||
|
||||
if (!documents.isEmpty()) {
|
||||
// now index unsaved data
|
||||
@@ -1434,6 +1438,9 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
boolean allDocsProcessed = true;
|
||||
try {
|
||||
for (Document document : documents) {
|
||||
if (psiBasedIndex && project != null && PsiDocumentManager.getInstance(project).isUncommited(document)) {
|
||||
continue;
|
||||
}
|
||||
allDocsProcessed &= indexUnsavedDocument(document, indexId, project, filter, restrictedFile);
|
||||
ProgressManager.checkCanceled();
|
||||
}
|
||||
@@ -1451,9 +1458,6 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
ProgressManager.checkCanceled();
|
||||
// assume all tasks were finished or cancelled in the same time
|
||||
// safe to set the flag here, because it will be cleared under the WriteAction
|
||||
|
||||
// if we have uncommitted documents in unsaved documents, we may index old psi with new uncommitted doc,
|
||||
// to properly reindex with new psi / new doc we don't mark index up to date in this case (IDEA-111448)
|
||||
myUpToDateIndices.add(indexId);
|
||||
}
|
||||
}
|
||||
@@ -2505,17 +2509,25 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
PsiFile file = event.getFile();
|
||||
if (file != null) {
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile instanceof VirtualFileWithId) {
|
||||
boolean wasIndexed = false;
|
||||
FileDocumentManager instance = FileDocumentManager.getInstance();
|
||||
Document document = instance.getDocument(virtualFile);
|
||||
if (document != null && instance.isDocumentUnsaved(document)) {
|
||||
for(ID<?,?> psiBackedIndex:myPsiDependentIndices) {
|
||||
if (isFileIndexed(virtualFile, psiBackedIndex)) {
|
||||
IndexingStamp.update(virtualFile, psiBackedIndex, IndexInfrastructure.INVALID_STAMP2);
|
||||
wasIndexed = true;
|
||||
}
|
||||
myUpToDateIndices.remove(psiBackedIndex);
|
||||
}
|
||||
if (wasIndexed) {
|
||||
myChangedFilesCollector.scheduleForUpdate(virtualFile);
|
||||
IndexingStamp.flushCache(virtualFile);
|
||||
} else { // change in persistent file
|
||||
if (virtualFile instanceof VirtualFileWithId) {
|
||||
boolean wasIndexed = false;
|
||||
for (ID<?, ?> psiBackedIndex : myPsiDependentIndices) {
|
||||
if (isFileIndexed(virtualFile, psiBackedIndex)) {
|
||||
IndexingStamp.update(virtualFile, psiBackedIndex, IndexInfrastructure.INVALID_STAMP2);
|
||||
wasIndexed = true;
|
||||
}
|
||||
}
|
||||
if (wasIndexed) {
|
||||
myChangedFilesCollector.scheduleForUpdate(virtualFile);
|
||||
IndexingStamp.flushCache(virtualFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
</options>
|
||||
<keywords keywords="#define;#else;#endif;#error;#if;#ifdef;#ifndef;#include;#line;#undef;auto;bool;break;case;char;const;continue;default;delete;do;double;else;enum;extern;false;float;for;goto;if;int;long;register;return;short;signed;sizeof;static;struct;switch;typedef;union;unsigned;void;volatile;while" ignore_case="false" />
|
||||
<keywords2 keywords="asm;catch;class;const_cast;dynamic_cast;explicit;friend;inline;mutable;namespace;new;operator;private;protected;public;reinterpret_cast;static_cast;this;throw;true;try;typeid;typename;using;virtual;wchar_t" />
|
||||
<keywords3 keywords="->" />
|
||||
</highlighting>
|
||||
</filetype>
|
||||
|
||||
|
||||
+10
@@ -283,6 +283,16 @@ IDENTIFIER ('k')
|
||||
'''
|
||||
}
|
||||
|
||||
public void testCpp() {
|
||||
SyntaxTable table = new SyntaxTable()
|
||||
table.addKeyword1('->')
|
||||
doTest table, "foo->bar", '''\
|
||||
IDENTIFIER ('foo')
|
||||
KEYWORD_1 ('->')
|
||||
IDENTIFIER ('bar')
|
||||
'''
|
||||
}
|
||||
|
||||
public void testNumber() {
|
||||
doTest createPropTable(), "1.23=1.24", '''\
|
||||
NUMBER ('1.23')
|
||||
|
||||
+6
@@ -1,6 +1,7 @@
|
||||
package com.intellij.remoteServer.runtime.deployment.debug;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -22,4 +23,9 @@ public class JavaDebugConnectionData implements DebugConnectionData {
|
||||
public int getPort() {
|
||||
return myPort;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JavaDebugServerModeHandler getServerModeHandler() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.remoteServer.runtime.deployment.debug;
|
||||
|
||||
import com.intellij.execution.ExecutionException;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public interface JavaDebugServerModeHandler {
|
||||
|
||||
void attachRemote() throws ExecutionException;
|
||||
|
||||
void detachRemote() throws ExecutionException;
|
||||
}
|
||||
@@ -126,7 +126,7 @@ public class UsagePreviewPanel extends UsageContextPanelBase {
|
||||
|
||||
TextRange elementRange = psiElement.getTextRange();
|
||||
TextRange infoRange = info.getRangeInElement();
|
||||
TextRange textRange = infoRange == null ? null : elementRange.intersection(infoRange);
|
||||
TextRange textRange = infoRange == null ? null : elementRange.cutOut(infoRange);
|
||||
if (textRange == null) textRange = elementRange;
|
||||
// hack to determine element range to highlight
|
||||
if (psiElement instanceof PsiNamedElement && !(psiElement instanceof PsiFile)) {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.openapi.util;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class AtomicNullableLazyValue<T> extends NullableLazyValue<T> {
|
||||
private volatile T myValue;
|
||||
private volatile boolean myComputed;
|
||||
|
||||
@Override
|
||||
public final T getValue() {
|
||||
boolean computed = myComputed;
|
||||
T value = myValue;
|
||||
if (computed) {
|
||||
return value;
|
||||
}
|
||||
synchronized (this) {
|
||||
computed = myComputed;
|
||||
value = myValue;
|
||||
if (!computed) {
|
||||
myValue = value = compute();
|
||||
myComputed = true;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ public class TestVcsNotifier extends VcsNotifier {
|
||||
return myLastNotification;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Notification notify(@NotNull NotificationGroup notificationGroup, @NotNull String title, @NotNull String message,
|
||||
@NotNull NotificationType type, @Nullable NotificationListener listener) {
|
||||
|
||||
@@ -27,6 +27,7 @@ public interface VcsLogBranchFilter extends VcsLogFilter {
|
||||
@NotNull
|
||||
Collection<String> getBranchNames();
|
||||
|
||||
// TODO remove from the API
|
||||
@NotNull
|
||||
Collection<Integer> getMatchingHeads();
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ import com.intellij.openapi.actionSystem.DataKey;
|
||||
*/
|
||||
public class VcsLogDataKeys {
|
||||
|
||||
public static DataKey<VcsLog> VSC_LOG = DataKey.create("Vcs.Log");
|
||||
public static final DataKey<VcsLog> VSC_LOG = DataKey.create("Vcs.Log");
|
||||
public static final DataKey<VcsLogUi> VCS_LOG_UI = DataKey.create("Vcs.Log.Ui");
|
||||
public static final DataKey<VcsLogDataProvider> VCS_LOG_DATA_PROVIDER = DataKey.create("Vcs.Log.DataProvider");
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface VcsLogDataPack {
|
||||
|
||||
@NotNull
|
||||
Map<VirtualFile, VcsLogProvider> getLogProviders();
|
||||
|
||||
@NotNull
|
||||
VcsLogRefs getRefs();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
*/
|
||||
public interface VcsLogDataProvider {
|
||||
|
||||
@NotNull
|
||||
Hash getHash(int commitIndex);
|
||||
|
||||
int getCommitIndex(@NotNull Hash hash);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
public interface VcsLogFilterChangeListener {
|
||||
|
||||
void filtersPossiblyChanged();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Graphical UI for filtering commits in the log.
|
||||
*/
|
||||
public interface VcsLogFilterUi {
|
||||
|
||||
/**
|
||||
* Returns the filters currently active, i.e. switched on by user.
|
||||
*/
|
||||
@NotNull
|
||||
VcsLogFilterCollection getFilters();
|
||||
|
||||
/**
|
||||
* Sets the given filter to the given value and updates the log view. <br/>
|
||||
* <b>Note:</b> only VcsLogBranchFilter is currently supported.
|
||||
*/
|
||||
void setFilter(@NotNull VcsLogFilter filter);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Allows to add some highlighting to the Vcs Log table entries.
|
||||
*/
|
||||
public interface VcsLogHighlighter {
|
||||
|
||||
/**
|
||||
* Return the color which should be used for the log table entries foreground, or null if default color should be used.
|
||||
* @param commitIndex index of commit (can be transferred to the Hash and vice versa).
|
||||
* @param isSelected if true, the row currently has selection on it.
|
||||
*/
|
||||
@Nullable
|
||||
Color getForeground(int commitIndex, boolean isSelected);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Collection of {@link VcsRef branches & tags references} which are in the log.
|
||||
*/
|
||||
public interface VcsLogRefs {
|
||||
|
||||
/**
|
||||
* Returns all branches.
|
||||
*/
|
||||
@NotNull
|
||||
Collection<VcsRef> getBranches();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface VcsLogUi {
|
||||
|
||||
@NotNull
|
||||
VcsLogFilterUi getFilterUi();
|
||||
|
||||
@NotNull
|
||||
VcsLogDataPack getDataPack();
|
||||
|
||||
void addHighlighter(@NotNull VcsLogHighlighter highlighter);
|
||||
void removeHighlighter(@NotNull VcsLogHighlighter highlighter);
|
||||
|
||||
void addFilterChangeListener(@NotNull VcsLogFilterChangeListener listener);
|
||||
void removeFilterChangeListener(@NotNull VcsLogFilterChangeListener listener);
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.intellij.vcs.log.graph.render;
|
||||
|
||||
import com.intellij.vcs.log.VcsRef;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author erokhins
|
||||
*/
|
||||
public class CommitCell {
|
||||
|
||||
private final String text;
|
||||
private final Collection<VcsRef> refsToThisCommit;
|
||||
|
||||
public CommitCell(@NotNull String text, @NotNull Collection<VcsRef> refsToThisCommit) {
|
||||
this.text = text;
|
||||
this.refsToThisCommit = refsToThisCommit;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public Collection<VcsRef> getRefsToThisCommit() {
|
||||
return refsToThisCommit;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,14 +5,24 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class GraphCommitCell {
|
||||
|
||||
/**
|
||||
* @author erokhins
|
||||
*/
|
||||
public class GraphCommitCell extends CommitCell {
|
||||
@NotNull private final String myText;
|
||||
@NotNull private final Collection<VcsRef> myRefsToThisCommit;
|
||||
|
||||
public GraphCommitCell(@NotNull String text, @NotNull Collection<VcsRef> refsToThisCommit) {
|
||||
super(text, refsToThisCommit);
|
||||
myText = text;
|
||||
myRefsToThisCommit = refsToThisCommit;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getText() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<VcsRef> getRefsToThisCommit() {
|
||||
return myRefsToThisCommit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -33,8 +33,8 @@ public abstract class AbstractTestWithTextFile {
|
||||
}
|
||||
|
||||
protected void doTest(String testName) throws IOException {
|
||||
String in = FileUtil.loadFile(new File(myDirectory + testName + IN_POSTFIX));
|
||||
String out = FileUtil.loadFile(new File(myDirectory + testName + OUT_POSTFIX));
|
||||
String in = FileUtil.loadFile(new File(myDirectory + testName + IN_POSTFIX), true);
|
||||
String out = FileUtil.loadFile(new File(myDirectory + testName + OUT_POSTFIX), true);
|
||||
runTest(in, out);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class DataPack {
|
||||
private static final boolean USE_NEW_FACADE = true;
|
||||
public class DataPack implements VcsLogDataPack {
|
||||
|
||||
private static final boolean USE_NEW_FACADE = true;
|
||||
|
||||
@NotNull private final RefsModel myRefsModel;
|
||||
@NotNull private final GraphFacade myGraphFacade;
|
||||
@NotNull private final Map<VirtualFile, VcsLogProvider> myLogProviders;
|
||||
|
||||
@NotNull
|
||||
public static DataPack build(@NotNull List<? extends GraphCommit> commits,
|
||||
@@ -25,20 +26,21 @@ public class DataPack {
|
||||
@NotNull ProgressIndicator indicator,
|
||||
@NotNull NotNullFunction<Hash, Integer> indexGetter,
|
||||
@NotNull NotNullFunction<Integer, Hash> hashGetter,
|
||||
@NotNull Map<VirtualFile, VcsLogProvider> logProviders) {
|
||||
@NotNull Map<VirtualFile, VcsLogProvider> providers) {
|
||||
indicator.setText("Building graph...");
|
||||
final RefsModel refsModel = new RefsModel(allRefs, indexGetter);
|
||||
GraphColorManagerImpl colorManager = new GraphColorManagerImpl(refsModel, hashGetter, getRefManagerMap(logProviders));
|
||||
GraphColorManagerImpl colorManager = new GraphColorManagerImpl(refsModel, hashGetter, getRefManagerMap(providers));
|
||||
if (USE_NEW_FACADE) {
|
||||
if (!commits.isEmpty()) {
|
||||
return new DataPack(refsModel, GraphFacadeImpl.newInstance(commits, getBranchCommitHashIndexes(allRefs, indexGetter), colorManager));
|
||||
return new DataPack(refsModel, GraphFacadeImpl.newInstance(commits, getBranchCommitHashIndexes(allRefs, indexGetter), colorManager),
|
||||
providers);
|
||||
}
|
||||
else {
|
||||
return new DataPack(refsModel, new EmptyGraphFacade());
|
||||
return new DataPack(refsModel, new EmptyGraphFacade(), providers);
|
||||
}
|
||||
} else {
|
||||
GraphFacade graphFacade = new GraphFacadeBuilderImpl().build(commits, refsModel, colorManager);
|
||||
return new DataPack(refsModel, graphFacade);
|
||||
return new DataPack(refsModel, graphFacade, providers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,9 +64,10 @@ public class DataPack {
|
||||
return map;
|
||||
}
|
||||
|
||||
private DataPack(@NotNull RefsModel refsModel, @NotNull GraphFacade graphFacade) {
|
||||
private DataPack(@NotNull RefsModel refsModel, @NotNull GraphFacade graphFacade, @NotNull Map<VirtualFile, VcsLogProvider> providers) {
|
||||
myRefsModel = refsModel;
|
||||
myGraphFacade = graphFacade;
|
||||
myLogProviders = providers;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -72,9 +75,21 @@ public class DataPack {
|
||||
return myGraphFacade;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VcsLogRefs getRefs() {
|
||||
return myRefsModel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public RefsModel getRefsModel() {
|
||||
return myRefsModel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Map<VirtualFile, VcsLogProvider> getLogProviders() {
|
||||
return myLogProviders;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.vcs.log.Hash;
|
||||
import com.intellij.vcs.log.VcsLogRefs;
|
||||
import com.intellij.vcs.log.VcsRef;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -14,10 +15,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author erokhins
|
||||
*/
|
||||
public class RefsModel {
|
||||
public class RefsModel implements VcsLogRefs {
|
||||
|
||||
@NotNull private final Collection<VcsRef> myBranches;
|
||||
@NotNull private final MultiMap<Hash, VcsRef> myRefsToHashes;
|
||||
@@ -80,6 +78,7 @@ public class RefsModel {
|
||||
return myRefsToIndices.containsKey(index) ? myRefsToIndices.get(index) : Collections.<VcsRef>emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Collection<VcsRef> getBranches() {
|
||||
return myBranches;
|
||||
|
||||
@@ -82,7 +82,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class VcsLogDataHolder implements Disposable {
|
||||
public class VcsLogDataHolder implements Disposable, VcsLogDataProvider {
|
||||
|
||||
public static final Topic<VcsLogRefreshListener> REFRESH_COMPLETED = Topic.create("Vcs.Log.Completed", VcsLogRefreshListener.class);
|
||||
|
||||
@@ -177,12 +177,13 @@ public class VcsLogDataHolder implements Disposable {
|
||||
@NotNull
|
||||
@Override
|
||||
public Integer fun(Hash hash) {
|
||||
return putHash(hash);
|
||||
return getCommitIndex(hash);
|
||||
}
|
||||
};
|
||||
myContainingBranchesGetter = new ContainingBranchesGetter(this, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Hash getHash(int commitIndex) {
|
||||
try {
|
||||
@@ -197,7 +198,8 @@ public class VcsLogDataHolder implements Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
public int putHash(@NotNull Hash hash) {
|
||||
@Override
|
||||
public int getCommitIndex(@NotNull Hash hash) {
|
||||
try {
|
||||
return myHashMap.getOrPut(hash);
|
||||
}
|
||||
@@ -839,15 +841,15 @@ public class VcsLogDataHolder implements Disposable {
|
||||
}
|
||||
|
||||
public CompactCommit(Hash hash, List<Hash> parents, long time) {
|
||||
myHashIndex = putHash(hash);
|
||||
myHashIndex = getCommitIndex(hash);
|
||||
myTime = time;
|
||||
|
||||
if (!parents.isEmpty()) {
|
||||
myParent = putHash(parents.get(0));
|
||||
myParent = getCommitIndex(parents.get(0));
|
||||
if (parents.size() > 1) {
|
||||
myOtherParents = new int[parents.size() - 1];
|
||||
for (int i = 0; i < parents.size() - 1; i++) {
|
||||
myOtherParents[i]= putHash(parents.get(i + 1));
|
||||
myOtherParents[i]= getCommitIndex(parents.get(i + 1));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.impl.VcsLogUtil;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel;
|
||||
import com.intellij.vcs.log.ui.tables.EmptyTableModel;
|
||||
import com.intellij.vcs.log.ui.tables.GraphTableModel;
|
||||
@@ -28,9 +28,9 @@ public class VcsLogFilterer {
|
||||
private static final int LOAD_MORE_COMMITS_FIRST_STEP_LIMIT = 200;
|
||||
|
||||
@NotNull private final VcsLogDataHolder myLogDataHolder;
|
||||
@NotNull private final VcsLogUI myUI;
|
||||
@NotNull private final VcsLogUiImpl myUI;
|
||||
|
||||
public VcsLogFilterer(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUI ui) {
|
||||
public VcsLogFilterer(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUiImpl ui) {
|
||||
myLogDataHolder = logDataHolder;
|
||||
myUI = ui;
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class VcsLogFilterer {
|
||||
final Set<Integer> commitSet = ContainerUtil.map2Set(filteredCommits, new Function<Hash, Integer>() {
|
||||
@Override
|
||||
public Integer fun(Hash hash) {
|
||||
return myLogDataHolder.putHash(hash);
|
||||
return myLogDataHolder.getCommitIndex(hash);
|
||||
}
|
||||
});
|
||||
return new Condition<Integer>() {
|
||||
|
||||
@@ -208,54 +208,55 @@ public class VcsLogJoiner {
|
||||
/*package*/ static class NewCommitIntegrator<Commit extends TimedVcsCommit> {
|
||||
private final List<Commit> list;
|
||||
private final Map<Hash, Commit> newCommitsMap;
|
||||
private final Collection<Commit> newCommits;
|
||||
|
||||
private final Stack<Commit> commitsStack;
|
||||
|
||||
public NewCommitIntegrator(@NotNull List<Commit> list, @NotNull Collection<Commit> newCommits) {
|
||||
this.list = list;
|
||||
newCommitsMap = ContainerUtil.newHashMap();
|
||||
this.newCommits = newCommits;
|
||||
for (Commit commit : newCommits) {
|
||||
newCommitsMap.put(commit.getHash(), commit);
|
||||
}
|
||||
commitsStack = new Stack<Commit>();
|
||||
}
|
||||
|
||||
// return insert Index
|
||||
private void insertToList(@NotNull Commit commit) {
|
||||
if (!newCommitsMap.containsKey(commit.getHash())) {
|
||||
throw new IllegalStateException("Commit was inserted, but insert call again. Commit hash: " + commit.getHash());
|
||||
}
|
||||
//insert all parents commits
|
||||
for (Hash parentHash : commit.getParents()) {
|
||||
Commit parentCommit = newCommitsMap.get(parentHash);
|
||||
if (parentCommit != null) {
|
||||
insertToList(parentCommit);
|
||||
}
|
||||
}
|
||||
private void insertAllUseStack() {
|
||||
while (!newCommitsMap.isEmpty()) {
|
||||
commitsStack.push(newCommitsMap.values().iterator().next());
|
||||
while (!commitsStack.isEmpty()) {
|
||||
Commit currentCommit = commitsStack.peek();
|
||||
boolean allParentsWereAdded = true;
|
||||
for (Hash parentHash : currentCommit.getParents()) {
|
||||
Commit parentCommit = newCommitsMap.get(parentHash);
|
||||
if (parentCommit != null) {
|
||||
commitsStack.push(parentCommit);
|
||||
allParentsWereAdded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int insertIndex;
|
||||
HashSet<Hash> parents = new HashSet<Hash>(commit.getParents());
|
||||
for (insertIndex = 0; insertIndex < list.size(); insertIndex++) {
|
||||
Commit currentCommit = list.get(insertIndex);
|
||||
if (parents.contains(currentCommit.getHash()))
|
||||
break;
|
||||
if (currentCommit.getTime() < commit.getTime())
|
||||
break;
|
||||
}
|
||||
if (!allParentsWereAdded)
|
||||
continue;
|
||||
|
||||
list.add(insertIndex, commit);
|
||||
newCommitsMap.remove(commit.getHash());
|
||||
}
|
||||
int insertIndex;
|
||||
HashSet<Hash> parents = new HashSet<Hash>(currentCommit.getParents());
|
||||
for (insertIndex = 0; insertIndex < list.size(); insertIndex++) {
|
||||
Commit someCommit = list.get(insertIndex);
|
||||
if (parents.contains(someCommit.getHash()))
|
||||
break;
|
||||
if (someCommit.getTime() < currentCommit.getTime())
|
||||
break;
|
||||
}
|
||||
|
||||
private void insertAllCommits() {
|
||||
for (Commit commit : newCommits) {
|
||||
if (newCommitsMap.get(commit.getHash()) != null) {
|
||||
insertToList(commit);
|
||||
list.add(insertIndex, currentCommit);
|
||||
newCommitsMap.remove(currentCommit.getHash());
|
||||
commitsStack.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Commit> getResultList() {
|
||||
insertAllCommits();
|
||||
insertAllUseStack();
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -35,9 +35,9 @@ import java.util.List;
|
||||
public class VcsLogImpl implements VcsLog {
|
||||
|
||||
@NotNull private final VcsLogDataHolder myDataHolder;
|
||||
@NotNull private final VcsLogUI myUi;
|
||||
@NotNull private final VcsLogUiImpl myUi;
|
||||
|
||||
public VcsLogImpl(@NotNull VcsLogDataHolder holder, @NotNull VcsLogUI ui) {
|
||||
public VcsLogImpl(@NotNull VcsLogDataHolder holder, @NotNull VcsLogUiImpl ui) {
|
||||
myDataHolder = holder;
|
||||
myUi = ui;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import com.intellij.vcs.log.data.DataPack;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.data.VcsLogUiProperties;
|
||||
import com.intellij.vcs.log.ui.VcsLogColorManagerImpl;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -54,7 +54,7 @@ public class VcsLogManager implements Disposable {
|
||||
|
||||
private PostponeableLogRefresher myLogRefresher;
|
||||
private volatile VcsLogDataHolder myLogDataHolder;
|
||||
private volatile VcsLogUI myUi;
|
||||
private volatile VcsLogUiImpl myUi;
|
||||
|
||||
public VcsLogManager(@NotNull Project project, @NotNull ProjectLevelVcsManager vcsManager,
|
||||
@NotNull VcsLogSettings settings,
|
||||
@@ -75,7 +75,7 @@ public class VcsLogManager implements Disposable {
|
||||
myLogDataHolder.initialize(new PairConsumer<VcsLogDataHolder, DataPack>() {
|
||||
@Override
|
||||
public void consume(VcsLogDataHolder vcsLogDataHolder, DataPack dataPack) {
|
||||
VcsLogUI logUI = new VcsLogUI(vcsLogDataHolder, myProject, mySettings,
|
||||
VcsLogUiImpl logUI = new VcsLogUiImpl(vcsLogDataHolder, myProject, mySettings,
|
||||
new VcsLogColorManagerImpl(logProviders.keySet()), myUiProperties, dataPack);
|
||||
myLogDataHolder = vcsLogDataHolder;
|
||||
myUi = logUI;
|
||||
@@ -124,10 +124,10 @@ public class VcsLogManager implements Disposable {
|
||||
}
|
||||
|
||||
/**
|
||||
* The instance of the {@link VcsLogUI} or null if the log was not initialized yet.
|
||||
* The instance of the {@link com.intellij.vcs.log.ui.VcsLogUiImpl} or null if the log was not initialized yet.
|
||||
*/
|
||||
@Nullable
|
||||
public VcsLogUI getLogUi() {
|
||||
public VcsLogUiImpl getLogUi() {
|
||||
return myUi;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ public class VcsLogObjectsFactoryImpl implements VcsLogObjectsFactory {
|
||||
LOG.error("The log data holder should have been initialized at this point");
|
||||
return -1;
|
||||
}
|
||||
return dataHolder.putHash(hash);
|
||||
return dataHolder.getCommitIndex(hash);
|
||||
}
|
||||
}, commitHash, name, type, root);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class VcsLogQuickSettingsActions extends DumbAwareAction {
|
||||
}
|
||||
VcsLogSettings settings = ServiceManager.getService(project, VcsLogSettings.class);
|
||||
VcsLogManager logManager = ServiceManager.getService(project, VcsLogManager.class);
|
||||
VcsLogUI logUi = logManager.getLogUi();
|
||||
VcsLogUiImpl logUi = logManager.getLogUi();
|
||||
if (logUi == null) {
|
||||
return;
|
||||
}
|
||||
@@ -70,9 +70,9 @@ public class VcsLogQuickSettingsActions extends DumbAwareAction {
|
||||
private static class MySettingsActionGroup extends ActionGroup {
|
||||
|
||||
private final VcsLogSettings mySettings;
|
||||
private final VcsLogUI myUi;
|
||||
private final VcsLogUiImpl myUi;
|
||||
|
||||
public MySettingsActionGroup(VcsLogSettings settings, VcsLogUI ui) {
|
||||
public MySettingsActionGroup(VcsLogSettings settings, VcsLogUiImpl ui) {
|
||||
mySettings = settings;
|
||||
myUi = ui;
|
||||
}
|
||||
|
||||
+58
-14
@@ -1,18 +1,18 @@
|
||||
package com.intellij.vcs.log.ui;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.EmptyRunnable;
|
||||
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
|
||||
import com.intellij.util.PairFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcs.log.Hash;
|
||||
import com.intellij.vcs.log.VcsLog;
|
||||
import com.intellij.vcs.log.VcsLogFilterCollection;
|
||||
import com.intellij.vcs.log.VcsLogSettings;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.*;
|
||||
import com.intellij.vcs.log.graph.*;
|
||||
import com.intellij.vcs.log.impl.VcsLogImpl;
|
||||
@@ -27,17 +27,15 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.TableModel;
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author erokhins
|
||||
*/
|
||||
public class VcsLogUI {
|
||||
public class VcsLogUiImpl implements VcsLogUi, Disposable {
|
||||
|
||||
public static final String POPUP_ACTION_GROUP = "Vcs.Log.ContextMenu";
|
||||
public static final String TOOLBAR_ACTION_GROUP = "Vcs.Log.Toolbar";
|
||||
public static final String VCS_LOG_TABLE_PLACE = "Vcs.Log.ContextMenu";
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(VcsLogUI.class);
|
||||
private static final Logger LOG = Logger.getInstance(VcsLogUiImpl.class);
|
||||
|
||||
@NotNull private final VcsLogDataHolder myLogDataHolder;
|
||||
@NotNull private final MainFrame myMainFrame;
|
||||
@@ -46,14 +44,18 @@ public class VcsLogUI {
|
||||
@NotNull private final VcsLogFilterer myFilterer;
|
||||
@NotNull private final VcsLog myLog;
|
||||
|
||||
@NotNull private final Collection<VcsLogFilterChangeListener> myFilterChangeListeners = ContainerUtil.newArrayList();
|
||||
|
||||
@NotNull private DataPack myDataPack;
|
||||
|
||||
public VcsLogUI(@NotNull VcsLogDataHolder logDataHolder, @NotNull Project project, @NotNull VcsLogSettings settings,
|
||||
@NotNull VcsLogColorManager manager, @NotNull VcsLogUiProperties uiProperties, @NotNull DataPack initialDataPack) {
|
||||
public VcsLogUiImpl(@NotNull VcsLogDataHolder logDataHolder, @NotNull Project project, @NotNull VcsLogSettings settings,
|
||||
@NotNull VcsLogColorManager manager, @NotNull VcsLogUiProperties uiProperties, @NotNull DataPack initialDataPack) {
|
||||
myLogDataHolder = logDataHolder;
|
||||
myProject = project;
|
||||
myColorManager = manager;
|
||||
myDataPack = initialDataPack;
|
||||
Disposer.register(logDataHolder, this);
|
||||
|
||||
myFilterer = new VcsLogFilterer(logDataHolder, this);
|
||||
myLog = new VcsLogImpl(myLogDataHolder, this);
|
||||
myMainFrame = new MainFrame(myLogDataHolder, this, project, settings, uiProperties, myLog, initialDataPack);
|
||||
@@ -238,7 +240,7 @@ public class VcsLogUI {
|
||||
}
|
||||
|
||||
private void commitNotFound(@NotNull String commitHash) {
|
||||
if (collectFilters().isEmpty()) {
|
||||
if (getFilters().isEmpty()) {
|
||||
showMessage(MessageType.WARNING, "Commit " + commitHash + " not found");
|
||||
}
|
||||
else {
|
||||
@@ -279,13 +281,14 @@ public class VcsLogUI {
|
||||
runUnderModalProgress("Applying filters...", new Runnable() {
|
||||
public void run() {
|
||||
final TIntHashSet previouslySelected = getSelectedCommits();
|
||||
final AbstractVcsLogTableModel newModel = myFilterer.applyFiltersAndUpdateUi(dataPack, collectFilters());
|
||||
final AbstractVcsLogTableModel newModel = myFilterer.applyFiltersAndUpdateUi(dataPack, getFilters());
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myDataPack = dataPack;
|
||||
setModel(newModel, myDataPack, previouslySelected);
|
||||
myMainFrame.updateDataPack(myDataPack);
|
||||
fireFilterChangeEvent();
|
||||
repaintUI();
|
||||
|
||||
if (newModel.getRowCount() == 0) { // getValueAt won't be called for empty model => need to explicitly request to load more
|
||||
@@ -303,7 +306,7 @@ public class VcsLogUI {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VcsLogFilterCollection collectFilters() {
|
||||
public VcsLogFilterCollection getFilters() {
|
||||
return myMainFrame.getFilterUi().getFilters();
|
||||
}
|
||||
|
||||
@@ -338,9 +341,50 @@ public class VcsLogUI {
|
||||
return myLog;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VcsLogFilterUi getFilterUi() {
|
||||
return myMainFrame.getFilterUi();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public DataPack getDataPack() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
return myDataPack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHighlighter(@NotNull VcsLogHighlighter highlighter) {
|
||||
getTable().addHighlighter(highlighter);
|
||||
repaintUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeHighlighter(@NotNull VcsLogHighlighter highlighter) {
|
||||
getTable().removeHighlighter(highlighter);
|
||||
repaintUI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFilterChangeListener(@NotNull VcsLogFilterChangeListener listener) {
|
||||
myFilterChangeListeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFilterChangeListener(@NotNull VcsLogFilterChangeListener listener) {
|
||||
myFilterChangeListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void fireFilterChangeEvent() {
|
||||
for (VcsLogFilterChangeListener listener : myFilterChangeListeners) {
|
||||
listener.filtersPossiblyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
getTable().removeAllHighlighters();
|
||||
}
|
||||
|
||||
}
|
||||
+38
-25
@@ -16,14 +16,14 @@
|
||||
package com.intellij.vcs.log.ui.filter;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.RefsModel;
|
||||
import com.intellij.vcs.log.data.DataPack;
|
||||
import com.intellij.vcs.log.data.VcsLogBranchFilterImpl;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.data.VcsLogUiProperties;
|
||||
import com.intellij.vcs.log.impl.VcsLogUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -31,25 +31,21 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent<VcsLogBranchFilter> {
|
||||
public class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent<VcsLogBranchFilter> {
|
||||
|
||||
@NotNull private final VcsLogDataHolder myDataHolder;
|
||||
@NotNull private final VcsLogUiProperties myUiProperties;
|
||||
|
||||
@NotNull private RefsModel myRefsModel;
|
||||
@NotNull private VcsLogDataPack myDataPack;
|
||||
|
||||
BranchFilterPopupComponent(@NotNull VcsLogClassicFilterUi filterUi,
|
||||
@NotNull VcsLogDataHolder dataHolder,
|
||||
@NotNull RefsModel refsModel,
|
||||
@NotNull VcsLogUiProperties uiProperties) {
|
||||
public BranchFilterPopupComponent(@NotNull VcsLogClassicFilterUi filterUi, @NotNull VcsLogDataPack dataPack,
|
||||
@NotNull VcsLogUiProperties uiProperties) {
|
||||
super(filterUi, "Branch");
|
||||
myDataHolder = dataHolder;
|
||||
myRefsModel = refsModel;
|
||||
myDataPack = dataPack;
|
||||
myUiProperties = uiProperties;
|
||||
}
|
||||
|
||||
void updateRefsModel(@NotNull RefsModel refsModel) {
|
||||
myRefsModel = refsModel;
|
||||
void updateDataPack(@NotNull DataPack dataPack) {
|
||||
myDataPack = dataPack;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,39 +55,56 @@ class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent<VcsLo
|
||||
actionGroup.add(createAllAction());
|
||||
actionGroup.add(createSelectMultipleValuesAction());
|
||||
|
||||
actionGroup.add(constructActionGroup(myDataPack, createRecentItemsActionGroup(), new Function<String, AnAction>() {
|
||||
@Override
|
||||
public AnAction fun(String name) {
|
||||
return createPredefinedValueAction(Collections.singleton(name));
|
||||
}
|
||||
}));
|
||||
return actionGroup;
|
||||
}
|
||||
|
||||
public static ActionGroup constructActionGroup(@NotNull VcsLogDataPack dataPack, @Nullable ActionGroup recentItemsGroup,
|
||||
@NotNull Function<String, AnAction> actionGetter) {
|
||||
Groups groups = prepareGroups(dataPack);
|
||||
return getFilteredActionGroup(groups, recentItemsGroup, actionGetter);
|
||||
}
|
||||
|
||||
private static Groups prepareGroups(@NotNull VcsLogDataPack dataPack) {
|
||||
Groups filteredGroups = new Groups();
|
||||
Collection<VcsRef> allRefs = myRefsModel.getBranches();
|
||||
Collection<VcsRef> allRefs = dataPack.getRefs().getBranches();
|
||||
for (Map.Entry<VirtualFile, Collection<VcsRef>> entry : VcsLogUtil.groupRefsByRoot(allRefs).entrySet()) {
|
||||
VirtualFile root = entry.getKey();
|
||||
Collection<VcsRef> refs = entry.getValue();
|
||||
VcsLogProvider provider = myDataHolder.getLogProvider(root);
|
||||
VcsLogProvider provider = dataPack.getLogProviders().get(root);
|
||||
VcsLogRefManager refManager = provider.getReferenceManager();
|
||||
List<RefGroup> refGroups = refManager.group(refs);
|
||||
|
||||
orderRefGroups(refGroups, filteredGroups);
|
||||
}
|
||||
|
||||
actionGroup.add(getFilteredActionGroup(filteredGroups));
|
||||
return actionGroup;
|
||||
return filteredGroups;
|
||||
}
|
||||
|
||||
private DefaultActionGroup getFilteredActionGroup(Groups groups) {
|
||||
private static DefaultActionGroup getFilteredActionGroup(@NotNull Groups groups, @Nullable ActionGroup recentItems,
|
||||
@NotNull Function<String, AnAction> actionGetter) {
|
||||
DefaultActionGroup actionGroup = new DefaultActionGroup();
|
||||
for (String single : groups.singletonGroups) {
|
||||
actionGroup.add(createPredefinedValueAction(Collections.singleton(single)));
|
||||
actionGroup.add(actionGetter.fun(single));
|
||||
}
|
||||
if (recentItems != null) {
|
||||
actionGroup.add(recentItems);
|
||||
}
|
||||
actionGroup.add(createRecentItemsActionGroup());
|
||||
for (Map.Entry<String, TreeSet<String>> group : groups.expandedGroups.entrySet()) {
|
||||
actionGroup.addSeparator(group.getKey());
|
||||
for (String action : group.getValue()) {
|
||||
actionGroup.add(createPredefinedValueAction(Collections.singleton(action)));
|
||||
actionGroup.add(actionGetter.fun(action));
|
||||
}
|
||||
}
|
||||
actionGroup.addSeparator();
|
||||
for (Map.Entry<String, TreeSet<String>> group : groups.collapsedGroups.entrySet()) {
|
||||
DefaultActionGroup popupGroup = new DefaultActionGroup(group.getKey(), true);
|
||||
for (String action : group.getValue()) {
|
||||
popupGroup.add(createPredefinedValueAction(Collections.singleton(action)));
|
||||
popupGroup.add(actionGetter.fun(action));
|
||||
}
|
||||
actionGroup.add(popupGroup);
|
||||
}
|
||||
@@ -145,7 +158,7 @@ class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent<VcsLo
|
||||
if (getSelectedValues() == null) {
|
||||
return null;
|
||||
}
|
||||
Collection<VcsRef> allBranches = myRefsModel.getBranches();
|
||||
Collection<VcsRef> allBranches = myDataPack.getRefs().getBranches();
|
||||
return new VcsLogBranchFilterImpl(allBranches, getSelectedValues());
|
||||
}
|
||||
|
||||
@@ -165,7 +178,7 @@ class BranchFilterPopupComponent extends MultipleValueFilterPopupComponent<VcsLo
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<String> getAllValues() {
|
||||
return ContainerUtil.map(myRefsModel.getBranches(), new Function<VcsRef, String>() {
|
||||
return ContainerUtil.map(myDataPack.getRefs().getBranches(), new Function<VcsRef, String>() {
|
||||
@Override
|
||||
public String fun(VcsRef ref) {
|
||||
return ref.getName();
|
||||
|
||||
+3
-3
@@ -69,7 +69,7 @@ abstract class MultipleValueFilterPopupComponent<Filter extends VcsLogFilter> ex
|
||||
return group;
|
||||
}
|
||||
|
||||
private void apply(@Nullable Collection<String> values, String text, String tooltip) {
|
||||
void apply(@Nullable Collection<String> values, @NotNull String text, @NotNull String tooltip) {
|
||||
mySelectedValues = values;
|
||||
applyFilters();
|
||||
setValue(text, tooltip);
|
||||
@@ -79,7 +79,7 @@ abstract class MultipleValueFilterPopupComponent<Filter extends VcsLogFilter> ex
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String displayableText(@NotNull Collection<String> values) {
|
||||
static String displayableText(@NotNull Collection<String> values) {
|
||||
if (values.size() == 1) {
|
||||
return values.iterator().next();
|
||||
}
|
||||
@@ -87,7 +87,7 @@ abstract class MultipleValueFilterPopupComponent<Filter extends VcsLogFilter> ex
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String tooltip(@NotNull Collection<String> values) {
|
||||
static String tooltip(@NotNull Collection<String> values) {
|
||||
return StringUtil.join(values, ", ");
|
||||
}
|
||||
|
||||
|
||||
+20
-10
@@ -24,25 +24,25 @@ import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.ui.SearchTextField;
|
||||
import com.intellij.ui.SearchTextFieldWithStoredHistory;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcs.log.VcsLogFilterCollection;
|
||||
import com.intellij.vcs.log.VcsLogTextFilter;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.DataPack;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.data.VcsLogUiProperties;
|
||||
import com.intellij.vcs.log.impl.VcsLogFilterCollectionImpl;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class VcsLogClassicFilterUi implements VcsLogFilterUi {
|
||||
|
||||
@NotNull private final SearchTextField myTextFilter;
|
||||
@NotNull private final VcsLogUI myUi;
|
||||
@NotNull private final VcsLogUiImpl myUi;
|
||||
@NotNull private final DefaultActionGroup myActionGroup;
|
||||
|
||||
@NotNull private final BranchFilterPopupComponent myBranchFilterComponent;
|
||||
@@ -50,7 +50,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
|
||||
@NotNull private final DateFilterPopupComponent myDateFilterComponent;
|
||||
@NotNull private final StructureFilterPopupComponent myStructureFilterComponent;
|
||||
|
||||
public VcsLogClassicFilterUi(@NotNull VcsLogUI ui, @NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUiProperties uiProperties,
|
||||
public VcsLogClassicFilterUi(@NotNull VcsLogUiImpl ui, @NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUiProperties uiProperties,
|
||||
@NotNull DataPack initialDataPack) {
|
||||
myUi = ui;
|
||||
|
||||
@@ -63,7 +63,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
|
||||
}
|
||||
});
|
||||
|
||||
myBranchFilterComponent = new BranchFilterPopupComponent(this, logDataHolder, initialDataPack.getRefsModel(), uiProperties);
|
||||
myBranchFilterComponent = new BranchFilterPopupComponent(this, initialDataPack, uiProperties);
|
||||
myUserFilterComponent = new UserFilterPopupComponent(this, logDataHolder, uiProperties);
|
||||
myDateFilterComponent = new DateFilterPopupComponent(this);
|
||||
myStructureFilterComponent = new StructureFilterPopupComponent(this, logDataHolder.getRoots());
|
||||
@@ -76,12 +76,14 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
|
||||
myActionGroup.add(new FilterActionComponent(myStructureFilterComponent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDataPack(@NotNull DataPack dataPack) {
|
||||
myBranchFilterComponent.updateRefsModel(dataPack.getRefsModel());
|
||||
myBranchFilterComponent.updateDataPack(dataPack);
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Returns filter components which will be added to the Log toolbar.
|
||||
*/
|
||||
@NotNull
|
||||
public ActionGroup getFilterActionComponents() {
|
||||
return myActionGroup;
|
||||
}
|
||||
@@ -94,11 +96,19 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
|
||||
myDateFilterComponent.getFilter(), textFilter, myStructureFilterComponent.getFilter());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFilter(@NotNull VcsLogFilter filter) {
|
||||
if (filter instanceof VcsLogBranchFilter) {
|
||||
Collection<String> values = ((VcsLogBranchFilter)filter).getBranchNames();
|
||||
myBranchFilterComponent.apply(values, MultipleValueFilterPopupComponent.displayableText(values),
|
||||
MultipleValueFilterPopupComponent.tooltip(values));
|
||||
}
|
||||
}
|
||||
|
||||
void applyFilters() {
|
||||
myUi.applyFiltersAndUpdateUi();
|
||||
}
|
||||
|
||||
|
||||
private static class TextFilterComponent extends DumbAwareAction implements CustomComponentAction {
|
||||
|
||||
private final SearchTextField mySearchField;
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.intellij.vcs.log.ui.filter;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.vcs.log.VcsLogFilterCollection;
|
||||
import com.intellij.vcs.log.data.DataPack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Graphical UI for filtering commits in the log.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public interface VcsLogFilterUi {
|
||||
|
||||
/**
|
||||
* Returns filter components which will be added to the Log toolbar.
|
||||
*/
|
||||
ActionGroup getFilterActionComponents();
|
||||
|
||||
/**
|
||||
* Returns the filters currently active, i.e. switched on by user.
|
||||
*/
|
||||
@NotNull
|
||||
VcsLogFilterCollection getFilters();
|
||||
|
||||
/**
|
||||
* Informs components that the actual DataPack has been updated (e.g. due to a log refresh). <br/>
|
||||
* Components may want to update their fields and/or rebuild.
|
||||
* @param dataPack new data pack.
|
||||
*/
|
||||
void updateDataPack(@NotNull DataPack dataPack);
|
||||
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.data.VcsLogRefreshListener;
|
||||
import com.intellij.vcs.log.impl.SingletonRefGroup;
|
||||
import com.intellij.vcs.log.impl.VcsLogUtil;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import com.intellij.vcs.log.ui.render.RefPainter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -46,14 +46,14 @@ import static com.intellij.vcs.log.graph.render.PrintParameters.HEIGHT_CELL;
|
||||
public class BranchesPanel extends JPanel {
|
||||
|
||||
private final VcsLogDataHolder myDataHolder;
|
||||
private final VcsLogUI myUI;
|
||||
private final VcsLogUiImpl myUI;
|
||||
|
||||
private List<RefGroup> myRefGroups;
|
||||
private final RefPainter myRefPainter;
|
||||
|
||||
private Map<Integer, RefGroup> myRefPositions = ContainerUtil.newHashMap();
|
||||
|
||||
public BranchesPanel(@NotNull VcsLogDataHolder dataHolder, @NotNull VcsLogUI UI, @NotNull RefsModel initialRefsModel) {
|
||||
public BranchesPanel(@NotNull VcsLogDataHolder dataHolder, @NotNull VcsLogUiImpl UI, @NotNull RefsModel initialRefsModel) {
|
||||
myDataHolder = dataHolder;
|
||||
myUI = UI;
|
||||
myRefGroups = getRefsToDisplayOnPanel(initialRefsModel);
|
||||
@@ -162,14 +162,14 @@ public class BranchesPanel extends JPanel {
|
||||
|
||||
private final JBPopup myPopup;
|
||||
private final JBList myList;
|
||||
private final VcsLogUI myUi;
|
||||
private final VcsLogUiImpl myUi;
|
||||
private final RefPainter myRefPainter;
|
||||
|
||||
private final SingleRefComponent myRendererComponent;
|
||||
|
||||
private final ListCellRenderer myCellRenderer;
|
||||
|
||||
RefPopupComponent(RefGroup group, VcsLogUI ui, RefPainter refPainter) {
|
||||
RefPopupComponent(RefGroup group, VcsLogUiImpl ui, RefPainter refPainter) {
|
||||
super(new BorderLayout());
|
||||
myUi = ui;
|
||||
myRefPainter = refPainter;
|
||||
|
||||
@@ -22,9 +22,9 @@ import com.intellij.vcs.log.VcsLogSettings;
|
||||
import com.intellij.vcs.log.data.DataPack;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.data.VcsLogUiProperties;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import com.intellij.vcs.log.ui.filter.VcsLogClassicFilterUi;
|
||||
import com.intellij.vcs.log.ui.filter.VcsLogFilterUi;
|
||||
import com.intellij.vcs.log.VcsLogFilterUi;
|
||||
import com.intellij.vcs.log.ui.tables.GraphTableModel;
|
||||
import icons.VcsLogIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -40,11 +40,11 @@ import java.util.List;
|
||||
public class MainFrame extends JPanel implements TypeSafeDataProvider {
|
||||
|
||||
@NotNull private final VcsLogDataHolder myLogDataHolder;
|
||||
@NotNull private final VcsLogUI myUI;
|
||||
@NotNull private final VcsLogUiImpl myUI;
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final VcsLogUiProperties myUiProperties;
|
||||
@NotNull private final VcsLog myLog;
|
||||
@NotNull private final VcsLogFilterUi myFilterUi;
|
||||
@NotNull private final VcsLogClassicFilterUi myFilterUi;
|
||||
|
||||
@NotNull private final JBLoadingPanel myChangesLoadingPane;
|
||||
@NotNull private final VcsLogGraphTable myGraphTable;
|
||||
@@ -53,7 +53,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
|
||||
@NotNull private final Splitter myDetailsSplitter;
|
||||
private final JComponent myToolbar;
|
||||
|
||||
public MainFrame(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUI vcsLogUI, @NotNull Project project,
|
||||
public MainFrame(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUiImpl vcsLogUI, @NotNull Project project,
|
||||
@NotNull VcsLogSettings settings, @NotNull VcsLogUiProperties uiProperties, @NotNull VcsLog log,
|
||||
@NotNull DataPack initialDataPack) {
|
||||
// collect info
|
||||
@@ -195,7 +195,7 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
|
||||
|
||||
DefaultActionGroup toolbarGroup = new DefaultActionGroup(hideBranchesAction, showBranchesAction, showFullPatchAction, refreshAction,
|
||||
showDetailsAction);
|
||||
toolbarGroup.add(ActionManager.getInstance().getAction(VcsLogUI.TOOLBAR_ACTION_GROUP));
|
||||
toolbarGroup.add(ActionManager.getInstance().getAction(VcsLogUiImpl.TOOLBAR_ACTION_GROUP));
|
||||
|
||||
DefaultActionGroup mainGroup = new DefaultActionGroup();
|
||||
mainGroup.add(myFilterUi.getFilterActionComponents());
|
||||
@@ -224,6 +224,12 @@ public class MainFrame extends JPanel implements TypeSafeDataProvider {
|
||||
if (VcsLogDataKeys.VSC_LOG == key) {
|
||||
sink.put(key, myLog);
|
||||
}
|
||||
else if (VcsLogDataKeys.VCS_LOG_UI == key) {
|
||||
sink.put(key, myUI);
|
||||
}
|
||||
else if (VcsLogDataKeys.VCS_LOG_DATA_PROVIDER == key) {
|
||||
sink.put(key, myLogDataHolder);
|
||||
}
|
||||
else if (VcsDataKeys.CHANGES.equals(key)) {
|
||||
List<Change> selectedChanges = getSelectedChanges();
|
||||
if (selectedChanges != null) {
|
||||
|
||||
@@ -16,14 +16,13 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcs.log.Hash;
|
||||
import com.intellij.vcs.log.VcsLogHighlighter;
|
||||
import com.intellij.vcs.log.data.DataPack;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.graph.*;
|
||||
import com.intellij.vcs.log.graph.render.CommitCell;
|
||||
import com.intellij.vcs.log.graph.render.GraphCommitCell;
|
||||
import com.intellij.vcs.log.graph.render.PositionUtil;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.render.CommitCellRender;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import com.intellij.vcs.log.ui.render.GraphCommitCellRender;
|
||||
import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -37,6 +36,7 @@ import java.awt.*;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -50,25 +50,26 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
private static final int MAX_ROWS_TO_CALC_WIDTH = 1000;
|
||||
private static final int MAX_ROWS_TO_CALC_OFFSET = 100;
|
||||
|
||||
@NotNull private final VcsLogUI myUI;
|
||||
@NotNull private final VcsLogUiImpl myUI;
|
||||
private final VcsLogDataHolder myLogDataHolder;
|
||||
private final GraphCommitCellRender myGraphCommitCellRender;
|
||||
|
||||
private boolean myColumnsSizeInitialized = false;
|
||||
private volatile boolean myRepaintFreezed;
|
||||
|
||||
@NotNull private final Collection<VcsLogHighlighter> myHighlighters = ContainerUtil.newArrayList();
|
||||
|
||||
@NotNull private DataPack myDataPack;
|
||||
|
||||
public VcsLogGraphTable(@NotNull VcsLogUI UI, @NotNull final VcsLogDataHolder logDataHolder, @NotNull DataPack initialDataPack) {
|
||||
public VcsLogGraphTable(@NotNull VcsLogUiImpl UI, @NotNull final VcsLogDataHolder logDataHolder, @NotNull DataPack initialDataPack) {
|
||||
super();
|
||||
myUI = UI;
|
||||
myLogDataHolder = logDataHolder;
|
||||
myDataPack = initialDataPack;
|
||||
myGraphCommitCellRender = new GraphCommitCellRender(myUI.getColorManager(), logDataHolder, myDataPack.getGraphFacade());
|
||||
myGraphCommitCellRender = new GraphCommitCellRender(myUI.getColorManager(), logDataHolder, myDataPack.getGraphFacade(), this);
|
||||
|
||||
setDefaultRenderer(VirtualFile.class, new RootCellRenderer(myUI));
|
||||
setDefaultRenderer(GraphCommitCell.class, myGraphCommitCellRender);
|
||||
setDefaultRenderer(CommitCell.class, new CommitCellRender(myUI.getColorManager(), logDataHolder));
|
||||
setDefaultRenderer(String.class, new StringCellRenderer());
|
||||
|
||||
setRowHeight(HEIGHT_CELL);
|
||||
@@ -89,7 +90,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
addMouseMotionListener(mouseAdapter);
|
||||
addMouseListener(mouseAdapter);
|
||||
|
||||
PopupHandler.installPopupHandler(this, VcsLogUI.POPUP_ACTION_GROUP, VcsLogUI.VCS_LOG_TABLE_PLACE);
|
||||
PopupHandler.installPopupHandler(this, VcsLogUiImpl.POPUP_ACTION_GROUP, VcsLogUiImpl.VCS_LOG_TABLE_PLACE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -243,6 +244,32 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
myGraphCommitCellRender.updateGraphFacade(dataPack.getGraphFacade());
|
||||
}
|
||||
|
||||
public void addHighlighter(@NotNull VcsLogHighlighter highlighter) {
|
||||
myHighlighters.add(highlighter);
|
||||
}
|
||||
|
||||
public void removeHighlighter(@NotNull VcsLogHighlighter highlighter) {
|
||||
myHighlighters.remove(highlighter);
|
||||
}
|
||||
|
||||
public void removeAllHighlighters() {
|
||||
myHighlighters.clear();
|
||||
}
|
||||
|
||||
public void applyHighlighters(@NotNull Component rendererComponent, int row, boolean selected) {
|
||||
boolean fgUpdated = false;
|
||||
for (VcsLogHighlighter highlighter : myHighlighters) {
|
||||
Color color = highlighter.getForeground(myDataPack.getGraphFacade().getCommitAtRow(row), selected);
|
||||
if (color != null) {
|
||||
rendererComponent.setForeground(color);
|
||||
fgUpdated = true;
|
||||
}
|
||||
}
|
||||
if (!fgUpdated) { // reset highlighting if no-one wants to change it
|
||||
rendererComponent.setForeground(UIUtil.getTableForeground(selected));
|
||||
}
|
||||
}
|
||||
|
||||
private class MyMouseAdapter extends MouseAdapter {
|
||||
private final TableLinkMouseListener myLinkListener;
|
||||
|
||||
@@ -316,11 +343,11 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
|
||||
private static class RootCellRenderer extends JPanel implements TableCellRenderer {
|
||||
|
||||
@NotNull private final VcsLogUI myUi;
|
||||
@NotNull private final VcsLogUiImpl myUi;
|
||||
|
||||
@NotNull private Color myColor = UIUtil.getTableBackground();
|
||||
|
||||
RootCellRenderer(@NotNull VcsLogUI ui) {
|
||||
RootCellRenderer(@NotNull VcsLogUiImpl ui) {
|
||||
myUi = ui;
|
||||
}
|
||||
|
||||
@@ -349,6 +376,7 @@ public class VcsLogGraphTable extends JBTable implements TypeSafeDataProvider, C
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
Component rendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
setBackground(isSelected ? table.getSelectionBackground() : JBColor.WHITE);
|
||||
applyHighlighters(rendererComponent, row, isSelected);
|
||||
return rendererComponent;
|
||||
}
|
||||
|
||||
|
||||
+12
-7
@@ -10,8 +10,9 @@ import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcs.log.VcsRef;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.graph.PaintInfo;
|
||||
import com.intellij.vcs.log.graph.render.CommitCell;
|
||||
import com.intellij.vcs.log.graph.render.GraphCommitCell;
|
||||
import com.intellij.vcs.log.ui.VcsLogColorManager;
|
||||
import com.intellij.vcs.log.ui.frame.VcsLogGraphTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -27,6 +28,7 @@ public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer
|
||||
private static final Logger LOG = Logger.getInstance(AbstractPaddingCellRender.class);
|
||||
|
||||
@NotNull private final VcsLogDataHolder myDataHolder;
|
||||
@NotNull private final VcsLogGraphTable myGraphTable;
|
||||
|
||||
@NotNull private final RefPainter myRefPainter;
|
||||
@NotNull private final IssueLinkRenderer myIssueLinkRenderer;
|
||||
@@ -34,8 +36,10 @@ public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer
|
||||
@Nullable private PaintInfo myGraphImage;
|
||||
@Nullable private Collection<VcsRef> myRefs;
|
||||
|
||||
protected AbstractPaddingCellRender(@NotNull VcsLogColorManager colorManager, @NotNull VcsLogDataHolder dataHolder) {
|
||||
protected AbstractPaddingCellRender(@NotNull VcsLogColorManager colorManager, @NotNull VcsLogDataHolder dataHolder,
|
||||
@NotNull VcsLogGraphTable table) {
|
||||
myDataHolder = dataHolder;
|
||||
myGraphTable = table;
|
||||
myRefPainter = new RefPainter(colorManager, false);
|
||||
myIssueLinkRenderer = new IssueLinkRenderer(dataHolder.getProject(), this);
|
||||
}
|
||||
@@ -49,7 +53,7 @@ public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer
|
||||
return;
|
||||
}
|
||||
|
||||
CommitCell cell = getAssertCommitCell(value);
|
||||
GraphCommitCell cell = getAssertCommitCell(value);
|
||||
myGraphImage = getGraphImage(row);
|
||||
myRefs = cell.getRefsToThisCommit();
|
||||
|
||||
@@ -67,6 +71,7 @@ public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer
|
||||
|
||||
append("");
|
||||
appendFixedTextFragmentWidth(textPadding);
|
||||
myGraphTable.applyHighlighters(this, row, isSelected);
|
||||
myIssueLinkRenderer.appendTextWithLinks(cell.getText());
|
||||
}
|
||||
|
||||
@@ -82,14 +87,14 @@ public abstract class AbstractPaddingCellRender extends ColoredTableCellRenderer
|
||||
if (myGraphImage != null) {
|
||||
UIUtil.drawImage(g, myGraphImage.getImage(), 0, 0, null);
|
||||
}
|
||||
else if (this instanceof GraphCommitCellRender) { // TODO temporary diagnostics: why does graph sometimes disappear
|
||||
else { // TODO temporary diagnostics: why does graph sometimes disappear
|
||||
LOG.error("Image is null");
|
||||
}
|
||||
}
|
||||
|
||||
private static CommitCell getAssertCommitCell(Object value) {
|
||||
assert value instanceof CommitCell : "Value of incorrect class was supplied: " + value;
|
||||
return (CommitCell)value;
|
||||
private static GraphCommitCell getAssertCommitCell(Object value) {
|
||||
assert value instanceof GraphCommitCell : "Value of incorrect class was supplied: " + value;
|
||||
return (GraphCommitCell)value;
|
||||
}
|
||||
|
||||
protected void drawRefs(@NotNull Graphics2D g2, @NotNull Collection<VcsRef> refs, int padding) {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package com.intellij.vcs.log.ui.render;
|
||||
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.graph.PaintInfo;
|
||||
import com.intellij.vcs.log.ui.VcsLogColorManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CommitCellRender extends AbstractPaddingCellRender {
|
||||
|
||||
public CommitCellRender(@NotNull VcsLogColorManager colorManager, @NotNull VcsLogDataHolder dataHolder) {
|
||||
super(colorManager, dataHolder);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected PaintInfo getGraphImage(int row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.graph.GraphFacade;
|
||||
import com.intellij.vcs.log.graph.PaintInfo;
|
||||
import com.intellij.vcs.log.ui.VcsLogColorManager;
|
||||
import com.intellij.vcs.log.ui.frame.VcsLogGraphTable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -26,9 +27,9 @@ public class GraphCommitCellRender extends AbstractPaddingCellRender {
|
||||
|
||||
@NotNull private GraphFacade myGraphFacade;
|
||||
|
||||
public GraphCommitCellRender(@NotNull VcsLogColorManager colorManager,
|
||||
@NotNull VcsLogDataHolder dataHolder, @NotNull GraphFacade graphFacade) {
|
||||
super(colorManager, dataHolder);
|
||||
public GraphCommitCellRender(@NotNull VcsLogColorManager colorManager, @NotNull VcsLogDataHolder dataHolder,
|
||||
@NotNull GraphFacade graphFacade, @NotNull VcsLogGraphTable table) {
|
||||
super(colorManager, dataHolder, table);
|
||||
myGraphFacade = graphFacade;
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -12,7 +12,7 @@ import com.intellij.vcs.log.data.DataPack;
|
||||
import com.intellij.vcs.log.data.LoadMoreStage;
|
||||
import com.intellij.vcs.log.data.LoadingDetails;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -34,14 +34,14 @@ public abstract class AbstractVcsLogTableModel<CommitColumnClass> extends Abstra
|
||||
private static final String[] COLUMN_NAMES = {"", "Subject", "Author", "Date"};
|
||||
|
||||
@NotNull private final VcsLogDataHolder myLogDataHolder;
|
||||
@NotNull protected final VcsLogUI myUi;
|
||||
@NotNull protected final VcsLogUiImpl myUi;
|
||||
@NotNull protected final DataPack myDataPack;
|
||||
@NotNull private final LoadMoreStage myLoadMoreStage;
|
||||
|
||||
@NotNull private final AtomicBoolean myLoadMoreWasRequested = new AtomicBoolean();
|
||||
|
||||
|
||||
protected AbstractVcsLogTableModel(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUI ui, @NotNull DataPack dataPack,
|
||||
protected AbstractVcsLogTableModel(@NotNull VcsLogDataHolder logDataHolder, @NotNull VcsLogUiImpl ui, @NotNull DataPack dataPack,
|
||||
@NotNull LoadMoreStage loadMoreStage) {
|
||||
myLogDataHolder = logDataHolder;
|
||||
myUi = ui;
|
||||
@@ -72,7 +72,7 @@ public abstract class AbstractVcsLogTableModel<CommitColumnClass> extends Abstra
|
||||
if (myLoadMoreWasRequested.compareAndSet(false, true) // Don't send the request to VCS twice
|
||||
&& myLoadMoreStage != LoadMoreStage.ALL_REQUESTED) { // or when everything possible is loaded
|
||||
myUi.getTable().setPaintBusy(true);
|
||||
myUi.getFilterer().requestVcs(myDataPack, myUi.collectFilters(), myLoadMoreStage, onLoaded);
|
||||
myUi.getFilterer().requestVcs(myDataPack, myUi.getFilters(), myLoadMoreStage, onLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ public abstract class AbstractVcsLogTableModel<CommitColumnClass> extends Abstra
|
||||
* Returns true if not all data has been loaded, i.e. there is sense to {@link #requestToLoadMore(Runnable) request more data}.
|
||||
*/
|
||||
public boolean canRequestMore() {
|
||||
return !myUi.collectFilters().isEmpty() && myLoadMoreStage != LoadMoreStage.ALL_REQUESTED;
|
||||
return !myUi.getFilters().isEmpty() && myLoadMoreStage != LoadMoreStage.ALL_REQUESTED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.intellij.vcs.log.data.DataPack;
|
||||
import com.intellij.vcs.log.data.LoadMoreStage;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.graph.render.GraphCommitCell;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -32,7 +32,7 @@ import java.util.Collections;
|
||||
public class EmptyTableModel extends AbstractVcsLogTableModel<GraphCommitCell> {
|
||||
|
||||
public EmptyTableModel(@NotNull DataPack dataPack, @NotNull VcsLogDataHolder logDataHolder,
|
||||
@NotNull VcsLogUI ui, @NotNull LoadMoreStage loadMoreStage) {
|
||||
@NotNull VcsLogUiImpl ui, @NotNull LoadMoreStage loadMoreStage) {
|
||||
super(logDataHolder, ui, dataPack, loadMoreStage);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.intellij.vcs.log.data.LoadMoreStage;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.graph.render.GraphCommitCell;
|
||||
import com.intellij.vcs.log.impl.VcsLogUtil;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -27,7 +27,7 @@ public class GraphTableModel extends AbstractVcsLogTableModel<GraphCommitCell> {
|
||||
@NotNull private final DataPack myDataPack;
|
||||
@NotNull private final VcsLogDataHolder myDataHolder;
|
||||
|
||||
public GraphTableModel(@NotNull DataPack dataPack, @NotNull VcsLogDataHolder dataHolder, @NotNull VcsLogUI UI,
|
||||
public GraphTableModel(@NotNull DataPack dataPack, @NotNull VcsLogDataHolder dataHolder, @NotNull VcsLogUiImpl UI,
|
||||
@NotNull LoadMoreStage loadMoreStage) {
|
||||
super(dataHolder, UI, dataPack, loadMoreStage);
|
||||
myDataPack = dataPack;
|
||||
@@ -44,7 +44,7 @@ public class GraphTableModel extends AbstractVcsLogTableModel<GraphCommitCell> {
|
||||
if (!myDataHolder.isFullLogShowing()) {
|
||||
myDataHolder.showFullLog(onLoaded);
|
||||
}
|
||||
else if (!myUi.collectFilters().isEmpty()) {
|
||||
else if (!myUi.getFilters().isEmpty()) {
|
||||
super.requestToLoadMore(onLoaded);
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ public class GraphTableModel extends AbstractVcsLogTableModel<GraphCommitCell> {
|
||||
|
||||
@Override
|
||||
public int getRowOfCommit(@NotNull final Hash hash) {
|
||||
final int commitIndex = myDataHolder.putHash(hash);
|
||||
final int commitIndex = myDataHolder.getCommitIndex(hash);
|
||||
return ContainerUtil.indexOf(VcsLogUtil.getVisibleCommits(myDataPack.getGraphFacade()), new Condition<Integer>() {
|
||||
@Override
|
||||
public boolean value(Integer integer) {
|
||||
|
||||
+5
@@ -16,6 +16,7 @@
|
||||
package com.intellij.xdebugger.frame.presentation;
|
||||
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -35,6 +36,10 @@ public abstract class XValuePresentation {
|
||||
*/
|
||||
public abstract void renderValue(@NotNull XValueTextRenderer renderer);
|
||||
|
||||
public void renderValue(@NotNull XValue value, @NotNull XValueTextRenderer renderer) {
|
||||
renderValue(renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return separator between name and value in a debugger tree
|
||||
*/
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ public class XValueHint extends AbstractValueHint {
|
||||
|
||||
SimpleColoredText text = new SimpleColoredText();
|
||||
text.append(myExpression, XDebuggerUIConstants.VALUE_NAME_ATTRIBUTES);
|
||||
XValueNodeImpl.buildText(valuePresenter, text);
|
||||
XValueNodeImpl.buildText(result, valuePresenter, text);
|
||||
|
||||
if (!hasChildren) {
|
||||
SimpleColoredComponent component = HintUtil.createInformationComponent();
|
||||
|
||||
+4
-4
@@ -111,7 +111,7 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
public void applyPresentation(@Nullable Icon icon, @NotNull XValuePresentation valuePresentation, boolean hasChildren) {
|
||||
setIcon(icon);
|
||||
myValuePresentation = valuePresentation;
|
||||
myRawValue = XValuePresentationUtil.computeValueText(valuePresentation);
|
||||
myRawValue = XValuePresentationUtil.computeValueText(myValueContainer, valuePresentation);
|
||||
|
||||
updateText();
|
||||
setLeaf(!hasChildren);
|
||||
@@ -140,7 +140,7 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
}
|
||||
}
|
||||
appendName();
|
||||
buildText(myValuePresentation, myText);
|
||||
buildText(myValueContainer, myValuePresentation, myText);
|
||||
}
|
||||
|
||||
private void appendName() {
|
||||
@@ -150,13 +150,13 @@ public class XValueNodeImpl extends XValueContainerNode<XValue> implements XValu
|
||||
}
|
||||
}
|
||||
|
||||
public static void buildText(@NotNull XValuePresentation valuePresenter, @NotNull final ColoredTextContainer text) {
|
||||
public static void buildText(@NotNull XValue value, @NotNull XValuePresentation valuePresenter, @NotNull ColoredTextContainer text) {
|
||||
XValuePresentationUtil.appendSeparator(text, valuePresenter.getSeparator());
|
||||
String type = valuePresenter.getType();
|
||||
if (type != null) {
|
||||
text.append("{" + type + "} ", XDebuggerUIConstants.TYPE_ATTRIBUTES);
|
||||
}
|
||||
valuePresenter.renderValue(new XValueTextRendererImpl(text));
|
||||
valuePresenter.renderValue(value, new XValueTextRendererImpl(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-2
@@ -22,6 +22,7 @@ import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.ui.ColoredTextContainer;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.frame.presentation.XValuePresentation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -86,9 +87,9 @@ public class XValuePresentationUtil {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String computeValueText(@NotNull XValuePresentation presentation) {
|
||||
public static String computeValueText(@NotNull XValue value, @NotNull XValuePresentation presentation) {
|
||||
XValuePresentationTextExtractor extractor = new XValuePresentationTextExtractor();
|
||||
presentation.renderValue(extractor);
|
||||
presentation.renderValue(value, extractor);
|
||||
return extractor.getText();
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ public class XDebuggerTestUtil {
|
||||
}
|
||||
|
||||
public static XTestValueNode computePresentation(XValue value, long timeout) throws InterruptedException {
|
||||
XTestValueNode node = new XTestValueNode();
|
||||
XTestValueNode node = new XTestValueNode(value);
|
||||
if (value instanceof com.intellij.xdebugger.frame.XNamedValue) {
|
||||
node.myName = ((XNamedValue)value).getName();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.intellij.xdebugger;
|
||||
|
||||
import com.intellij.xdebugger.frame.XFullValueEvaluator;
|
||||
import com.intellij.xdebugger.frame.XValue;
|
||||
import com.intellij.xdebugger.frame.presentation.XValuePresentation;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodePresentationConfigurator;
|
||||
import com.intellij.xdebugger.impl.ui.tree.nodes.XValuePresentationUtil;
|
||||
@@ -20,12 +21,18 @@ public class XTestValueNode extends XValueNodePresentationConfigurator.Configura
|
||||
|
||||
private final Semaphore myFinished = new Semaphore(0);
|
||||
|
||||
private final XValue myXValue;
|
||||
|
||||
public XTestValueNode(@NotNull XValue value) {
|
||||
myXValue = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyPresentation(@Nullable Icon icon,
|
||||
@NotNull XValuePresentation valuePresentation,
|
||||
boolean hasChildren) {
|
||||
myType = valuePresentation.getType();
|
||||
myValue = XValuePresentationUtil.computeValueText(valuePresentation);
|
||||
myValue = XValuePresentationUtil.computeValueText(myXValue, valuePresentation);
|
||||
myHasChildren = hasChildren;
|
||||
|
||||
myFinished.release();
|
||||
|
||||
@@ -107,6 +107,9 @@
|
||||
<group id="Git.Log.Toolbar">
|
||||
<reference id="Git.CherryPick"/>
|
||||
<add-to-group group-id="Vcs.Log.Toolbar" />
|
||||
<action id="Git.Log.DeepCompare" class="git4idea.branch.DeepCompareAction" text="Highlight non-picked commits"
|
||||
icon="AllIcons.Diff.Diff"
|
||||
description="Dims those commits which have equivalent changes in the current branch"/>
|
||||
</group>
|
||||
|
||||
|
||||
@@ -174,6 +177,7 @@
|
||||
serviceImplementation="git4idea.branch.GitBrancherImpl"/>
|
||||
|
||||
<projectService serviceImplementation="git4idea.log.GitContentRevisionFactory" />
|
||||
<projectService serviceImplementation="git4idea.branch.DeepComparatorHolder"/>
|
||||
|
||||
<applicationService serviceImplementation="git4idea.history.wholeTree.GitCommitsSequentialIndex"
|
||||
serviceInterface="git4idea.history.wholeTree.GitCommitsSequentially"/>
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.branch;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.VcsNotifier;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.DataPack;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.data.VcsLogRefreshListener;
|
||||
import com.intellij.vcs.log.impl.HashImpl;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.commands.GitCommand;
|
||||
import git4idea.commands.GitLineHandler;
|
||||
import git4idea.commands.GitLineHandlerAdapter;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Map;
|
||||
|
||||
public class DeepComparator implements Disposable {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(DeepComparator.class);
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final GitRepositoryManager myRepositoryManager;
|
||||
@NotNull private final VcsLogUi myUi;
|
||||
@NotNull private final VcsLogFilterChangeListener myFilterChangeListener;
|
||||
|
||||
@Nullable private VcsLogHighlighter myHighlighter;
|
||||
@Nullable private MyTask myTask;
|
||||
|
||||
@NotNull
|
||||
public static DeepComparator getInstance(@NotNull Project project, @NotNull VcsLogUi ui) {
|
||||
DeepComparatorHolder holder = ServiceManager.getService(project, DeepComparatorHolder.class);
|
||||
return holder.getInstance(ui);
|
||||
}
|
||||
|
||||
DeepComparator(@NotNull Project project, @NotNull GitRepositoryManager manager, @NotNull VcsLogUi ui, @NotNull Disposable parent) {
|
||||
myProject = project;
|
||||
myRepositoryManager = manager;
|
||||
myUi = ui;
|
||||
Disposer.register(parent, this);
|
||||
|
||||
myFilterChangeListener = new VcsLogFilterChangeListener() {
|
||||
@Override
|
||||
public void filtersPossiblyChanged() {
|
||||
if (myTask == null) { // no task in progress => not interested in filter changes
|
||||
return;
|
||||
}
|
||||
|
||||
VcsLogBranchFilter branchFilter = myUi.getFilterUi().getFilters().getBranchFilter();
|
||||
if (branchFilter == null ||
|
||||
branchFilter.getBranchNames().size() != 1 ||
|
||||
!branchFilter.getBranchNames().iterator().next().equals(myTask.myComparedBranch)) {
|
||||
stopAndUnhighlight();
|
||||
}
|
||||
}
|
||||
};
|
||||
myUi.addFilterChangeListener(myFilterChangeListener);
|
||||
|
||||
project.getMessageBus().connect(project).subscribe(VcsLogDataHolder.REFRESH_COMPLETED, new VcsLogRefreshListener() {
|
||||
@Override
|
||||
public void refresh(@NotNull DataPack dataPack) {
|
||||
if (myTask == null) { // no task in progress => not interested in refresh events
|
||||
return;
|
||||
}
|
||||
|
||||
// collect data
|
||||
String comparedBranch = myTask.myComparedBranch;
|
||||
Map<GitRepository, GitBranch> repositoriesWithCurrentBranches = myTask.myRepositoriesWithCurrentBranches;
|
||||
VcsLogDataProvider provider = myTask.myProvider;
|
||||
|
||||
stopAndUnhighlight();
|
||||
|
||||
// highlight again
|
||||
Map<GitRepository, GitBranch> repositories = getRepositories(myUi.getDataPack().getLogProviders(), comparedBranch);
|
||||
if (repositories.equals(repositoriesWithCurrentBranches)) { // but not if current branch changed
|
||||
highlightInBackground(comparedBranch, provider);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void highlightInBackground(@NotNull String branchToCompare, @NotNull VcsLogDataProvider dataProvider) {
|
||||
if (myTask != null) {
|
||||
LOG.error("Shouldn't be possible");
|
||||
return;
|
||||
}
|
||||
|
||||
Map<GitRepository, GitBranch> repositories = getRepositories(myUi.getDataPack().getLogProviders(), branchToCompare);
|
||||
if (repositories.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
myTask = new MyTask(myProject, myUi, repositories, dataProvider, branchToCompare);
|
||||
myTask.queue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Map<GitRepository, GitBranch> getRepositories(@NotNull Map<VirtualFile, VcsLogProvider> providers,
|
||||
@NotNull String branchToCompare) {
|
||||
Map<GitRepository, GitBranch> repos = ContainerUtil.newHashMap();
|
||||
for (VirtualFile root : providers.keySet()) {
|
||||
GitRepository repository = myRepositoryManager.getRepositoryForRoot(root);
|
||||
if (repository == null || repository.getCurrentBranch() == null ||
|
||||
repository.getBranches().findBranchByName(branchToCompare) == null) {
|
||||
continue;
|
||||
}
|
||||
repos.put(repository, repository.getCurrentBranch());
|
||||
}
|
||||
return repos;
|
||||
}
|
||||
|
||||
public void stopAndUnhighlight() {
|
||||
if (myTask != null) {
|
||||
myTask.cancel();
|
||||
myTask = null;
|
||||
}
|
||||
if (myHighlighter != null) {
|
||||
myUi.removeHighlighter(myHighlighter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
stopAndUnhighlight();
|
||||
myUi.removeFilterChangeListener(myFilterChangeListener);
|
||||
}
|
||||
|
||||
public boolean hasHighlightingOrInProgress() {
|
||||
return myTask != null;
|
||||
}
|
||||
|
||||
private class MyTask extends Task.Backgroundable {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final VcsLogUi myUi;
|
||||
@NotNull private final Map<GitRepository, GitBranch> myRepositoriesWithCurrentBranches;
|
||||
@NotNull private final VcsLogDataProvider myProvider;
|
||||
@NotNull private final String myComparedBranch;
|
||||
|
||||
@NotNull private final TIntHashSet myNonPickedCommits = new TIntHashSet();
|
||||
@Nullable private VcsException myException;
|
||||
private boolean myCancelled;
|
||||
|
||||
public MyTask(@NotNull Project project, @NotNull VcsLogUi ui, @NotNull Map<GitRepository, GitBranch> repositoriesWithCurrentBranches,
|
||||
@NotNull VcsLogDataProvider dataProvider, @NotNull String branchToCompare) {
|
||||
super(project, "Comparing branches...");
|
||||
myProject = project;
|
||||
myUi = ui;
|
||||
myRepositoriesWithCurrentBranches = repositoriesWithCurrentBranches;
|
||||
myProvider = dataProvider;
|
||||
myComparedBranch = branchToCompare;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
try {
|
||||
for (Map.Entry<GitRepository, GitBranch> entry : myRepositoriesWithCurrentBranches.entrySet()) {
|
||||
GitRepository repo = entry.getKey();
|
||||
GitBranch currentBranch = entry.getValue();
|
||||
myNonPickedCommits.addAll(getNonPickedCommitsFromGit(myProject, repo.getRoot(), myProvider,
|
||||
currentBranch.getName(), myComparedBranch).toArray());
|
||||
}
|
||||
}
|
||||
catch (VcsException e) {
|
||||
LOG.warn(e);
|
||||
myException = e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
if (myCancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (myException != null) {
|
||||
VcsNotifier.getInstance(myProject).notifyError("Couldn't compare with branch " + myComparedBranch, myException.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if (myHighlighter != null) {
|
||||
myUi.removeHighlighter(myHighlighter);
|
||||
}
|
||||
myHighlighter = new VcsLogHighlighter() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Color getForeground(int commitIndex, boolean isSelected) {
|
||||
return !myNonPickedCommits.contains(commitIndex) ? JBColor.GRAY : null;
|
||||
}
|
||||
};
|
||||
myUi.addHighlighter(myHighlighter);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
myCancelled = true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TIntHashSet getNonPickedCommitsFromGit(@NotNull Project project, @NotNull VirtualFile root,
|
||||
@NotNull final VcsLogDataProvider dataProvider,
|
||||
@NotNull String currentBranch, @NotNull String comparedBranch) throws VcsException {
|
||||
GitLineHandler handler = new GitLineHandler(project, root, GitCommand.CHERRY);
|
||||
handler.addParameters(currentBranch, comparedBranch); // upstream - current branch; head - compared branch
|
||||
|
||||
final TIntHashSet pickedCommits = new TIntHashSet();
|
||||
handler.addLineListener(new GitLineHandlerAdapter() {
|
||||
@Override
|
||||
public void onLineAvailable(String line, Key outputType) {
|
||||
// + 645caac042ff7fb1a5e3f7d348f00e9ceea5c317
|
||||
// - c3b9b90f6c26affd7e597ebf65db96de8f7e5860
|
||||
if (line.startsWith("+")) {
|
||||
try {
|
||||
line = line.substring(2).trim();
|
||||
int firstSpace = line.indexOf(' ');
|
||||
if (firstSpace > 0) {
|
||||
line = line.substring(0, firstSpace); // safety-check: take just the first word for sure
|
||||
}
|
||||
Hash hash = HashImpl.build(line);
|
||||
pickedCommits.add(dataProvider.getCommitIndex(hash));
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Couldn't parse line [" + line + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
handler.runInCurrentThread(null);
|
||||
return pickedCommits;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.branch;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcs.log.VcsLogUi;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class DeepComparatorHolder implements Disposable {
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final GitRepositoryManager myRepositoryManager;
|
||||
|
||||
@NotNull private final Map<VcsLogUi, DeepComparator> myComparators;
|
||||
|
||||
// initialized by pico-container
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
private DeepComparatorHolder(@NotNull Project project, @NotNull GitRepositoryManager repositoryManager) {
|
||||
myProject = project;
|
||||
myRepositoryManager = repositoryManager;
|
||||
myComparators = ContainerUtil.newHashMap();
|
||||
Disposer.register(project, this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DeepComparator getInstance(@NotNull VcsLogUi ui) {
|
||||
DeepComparator comparator = myComparators.get(ui);
|
||||
if (comparator == null) {
|
||||
comparator = new DeepComparator(myProject, myRepositoryManager, ui, this);
|
||||
myComparators.put(ui, comparator);
|
||||
}
|
||||
return comparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
myComparators.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.branch;
|
||||
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.vcs.log.*;
|
||||
import com.intellij.vcs.log.data.VcsLogBranchFilterImpl;
|
||||
import com.intellij.vcs.log.ui.filter.BranchFilterPopupComponent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Collections;
|
||||
|
||||
public class DeepCompareAction extends ToggleAction implements DumbAware {
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
VcsLogUi ui = e.getData(VcsLogDataKeys.VCS_LOG_UI);
|
||||
if (project == null || ui == null) {
|
||||
return false;
|
||||
}
|
||||
return DeepComparator.getInstance(project, ui).hasHighlightingOrInProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean selected) {
|
||||
Project project = e.getData(CommonDataKeys.PROJECT);
|
||||
final VcsLogUi ui = e.getData(VcsLogDataKeys.VCS_LOG_UI);
|
||||
final VcsLogDataProvider dataProvider = e.getData(VcsLogDataKeys.VCS_LOG_DATA_PROVIDER);
|
||||
if (project == null || ui == null || dataProvider == null) {
|
||||
return;
|
||||
}
|
||||
final DeepComparator dc = DeepComparator.getInstance(project, ui);
|
||||
if (selected) {
|
||||
VcsLogBranchFilter branchFilter = ui.getFilterUi().getFilters().getBranchFilter();
|
||||
if (branchFilter == null || branchFilter.getBranchNames().size() != 1) {
|
||||
selectBranchAndPerformAction(ui.getDataPack(), e, new Consumer<String>() {
|
||||
@Override
|
||||
public void consume(String selectedBranch) {
|
||||
ui.getFilterUi().setFilter(new VcsLogBranchFilterImpl(ui.getDataPack().getRefs().getBranches(),
|
||||
Collections.singleton(selectedBranch)));
|
||||
dc.highlightInBackground(selectedBranch, dataProvider);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
String branchToCompare = branchFilter.getBranchNames().iterator().next();
|
||||
dc.highlightInBackground(branchToCompare, dataProvider);
|
||||
}
|
||||
else {
|
||||
dc.stopAndUnhighlight();
|
||||
}
|
||||
}
|
||||
|
||||
private static void selectBranchAndPerformAction(@NotNull VcsLogDataPack dataPack, @NotNull AnActionEvent event,
|
||||
@NotNull final Consumer<String> consumer) {
|
||||
ActionGroup actionGroup = BranchFilterPopupComponent.constructActionGroup(dataPack, null, new Function<String, AnAction>() {
|
||||
@Override
|
||||
public AnAction fun(final String s) {
|
||||
return new DumbAwareAction(s) {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
consumer.consume(s);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
ListPopup popup = JBPopupFactory.getInstance().createActionGroupPopup("Select branch to compare", actionGroup, event.getDataContext(),
|
||||
false, false, false, null, -1, null);
|
||||
InputEvent inputEvent = event.getInputEvent();
|
||||
if (inputEvent instanceof MouseEvent) {
|
||||
popup.show(new RelativePoint((MouseEvent)inputEvent));
|
||||
}
|
||||
else {
|
||||
popup.showInBestPositionFor(event.getDataContext());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
super.update(e);
|
||||
VcsLogUi ui = e.getData(VcsLogDataKeys.VCS_LOG_UI);
|
||||
e.getPresentation().setEnabledAndVisible(ui != null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,6 +41,7 @@ public class GitCommand {
|
||||
public static final GitCommand CHECK_ATTR = read("check-attr");
|
||||
public static final GitCommand COMMIT = write("commit");
|
||||
public static final GitCommand CONFIG = read("config");
|
||||
public static final GitCommand CHERRY = read("cherry");
|
||||
public static final GitCommand CHERRY_PICK = write("cherry-pick");
|
||||
public static final GitCommand CLONE = write("clone");
|
||||
public static final GitCommand DIFF = read("diff");
|
||||
|
||||
@@ -16,7 +16,7 @@ import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.content.ContentManager;
|
||||
import com.intellij.vcs.log.impl.VcsLogContentProvider;
|
||||
import com.intellij.vcs.log.impl.VcsLogManager;
|
||||
import com.intellij.vcs.log.ui.VcsLogUI;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -56,7 +56,7 @@ public class SelectRevisionInGitLogAction extends DumbAwareAction {
|
||||
Runnable selectCommit = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
VcsLogUI logUi = log.getLogUi();
|
||||
VcsLogUiImpl logUi = log.getLogUi();
|
||||
if (logUi == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.intellij.util.xml;
|
||||
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.xml.ui.DomUIFactory;
|
||||
import junit.framework.TestCase;
|
||||
import net.sf.cglib.proxy.AdvancedProxy;
|
||||
import net.sf.cglib.proxy.InvocationHandler;
|
||||
@@ -167,5 +168,26 @@ public class ProxyTest extends TestCase {
|
||||
assertEquals(((CovariantFromBaseClassTest.Intf)proxy).sayA(), "a");
|
||||
}
|
||||
|
||||
public void testGenericMethodInvocationJava8() throws Throwable {
|
||||
ConcreteInterface proxy = AdvancedProxy.createProxy(new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
return 42;
|
||||
}
|
||||
}, null, ConcreteInterface.class);
|
||||
Method foo = DomUIFactory.findMethod(GenericInterface.class, "foo");
|
||||
assert foo != null;
|
||||
assertEquals(42, proxy.foo("a"));
|
||||
assertEquals(42, foo.invoke(proxy, "a"));
|
||||
}
|
||||
|
||||
interface GenericInterface<T> {
|
||||
Object foo(T t);
|
||||
}
|
||||
|
||||
interface ConcreteInterface extends GenericInterface<String> {
|
||||
Object foo(String t);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user