Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Trofimov
2014-03-10 20:13:33 +01:00
76 changed files with 1613 additions and 618 deletions
@@ -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
@@ -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() {
@@ -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();
@@ -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());
@@ -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);
}
}
@@ -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) {
@@ -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
@@ -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();
}
@@ -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>
@@ -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')
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
@@ -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();
}
}
@@ -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();
@@ -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, ", ");
}
@@ -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;
}
@@ -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;
}
@@ -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) {
@@ -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
*/
@@ -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();
@@ -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
@@ -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();
+4
View File
@@ -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);
}
}