mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
+15
@@ -113,6 +113,21 @@ class Foo {
|
||||
'''
|
||||
}
|
||||
|
||||
public void "test complete variable name in string literal"() {
|
||||
myFixture.configureByText "a.java", '''
|
||||
class Xoo {
|
||||
String foobar = "foo<caret>";
|
||||
}
|
||||
'''
|
||||
complete()
|
||||
myFixture.checkResult '''
|
||||
class Xoo {
|
||||
String foobar = "foobar<caret>";
|
||||
}
|
||||
'''
|
||||
|
||||
}
|
||||
|
||||
private void complete() {
|
||||
myFixture.performEditorAction(IdeActions.ACTION_HIPPIE_COMPLETION)
|
||||
}
|
||||
|
||||
+9
-16
@@ -44,7 +44,6 @@ import java.util.*;
|
||||
*/
|
||||
public class HippieWordCompletionHandler implements CodeInsightActionHandler {
|
||||
private static final Key<CompletionState> KEY_STATE = new Key<CompletionState>("HIPPIE_COMPLETION_STATE");
|
||||
private static final String WHITESPACE_CHARS = " \t\n";
|
||||
private final boolean myForward;
|
||||
|
||||
public HippieWordCompletionHandler(boolean forward) {
|
||||
@@ -188,7 +187,7 @@ public class HippieWordCompletionHandler implements CodeInsightActionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isWordLike(CharSequence seq, int start, int end) {
|
||||
private static boolean containsLetters(CharSequence seq, int start, int end) {
|
||||
for (int i = start; i < end; i++) {
|
||||
if (Character.isLetter(seq.charAt(i))) {
|
||||
return true;
|
||||
@@ -256,7 +255,7 @@ public class HippieWordCompletionHandler implements CodeInsightActionHandler {
|
||||
@Override
|
||||
public boolean processToken(int start, int end) {
|
||||
if ((start > caretOffset || end < caretOffset) && //skip prefix itself
|
||||
end - start > matcher.getPrefix().length() && isWordLike(chars, start, end)) {
|
||||
end - start > matcher.getPrefix().length()) {
|
||||
final String word = chars.subSequence(start, end).toString();
|
||||
if (matcher.isStartMatch(word)) {
|
||||
CompletionVariant v = new CompletionVariant(editor, word, start);
|
||||
@@ -280,25 +279,15 @@ public class HippieWordCompletionHandler implements CodeInsightActionHandler {
|
||||
while (!iterator.atEnd()) {
|
||||
int start = iterator.getStart();
|
||||
int end = iterator.getEnd();
|
||||
if (StringUtil.indexOfAny(chars, WHITESPACE_CHARS, start, end) < 0) {
|
||||
//a single token without whitespace, consider it one word, even if it's an identifier with '-' inside
|
||||
if (isWordLike(chars, start, end) && !processor.processToken(start, end)) {
|
||||
return;
|
||||
}
|
||||
iterator.advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
// a token with whitespace inside (a string literal or comment)
|
||||
// use the default java-identifier notion of word
|
||||
while (start < end) {
|
||||
int wordStart = start;
|
||||
while (wordStart < end && !Character.isJavaIdentifierPart(chars.charAt(wordStart))) wordStart++;
|
||||
while (wordStart < end && !isWordPart(chars.charAt(wordStart))) wordStart++;
|
||||
|
||||
int wordEnd = wordStart;
|
||||
while (wordEnd < end && Character.isJavaIdentifierPart(chars.charAt(wordEnd))) wordEnd++;
|
||||
while (wordEnd < end && isWordPart(chars.charAt(wordEnd))) wordEnd++;
|
||||
|
||||
if (!processor.processToken(wordStart, wordEnd)) {
|
||||
if (wordEnd > wordStart && containsLetters(chars, wordStart, wordEnd) && !processor.processToken(wordStart, wordEnd)) {
|
||||
return;
|
||||
}
|
||||
start = wordEnd + 1;
|
||||
@@ -307,6 +296,10 @@ public class HippieWordCompletionHandler implements CodeInsightActionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isWordPart(final char c) {
|
||||
return Character.isJavaIdentifierPart(c) || c == '-' || c == '*' ;
|
||||
}
|
||||
|
||||
private static CompletionData computeData(final Editor editor, final CharSequence charsSequence) {
|
||||
final int offset = editor.getCaretModel().getOffset();
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
@@ -86,7 +87,7 @@ public class GotoActionAction extends GotoActionBase implements DumbAware {
|
||||
final String enteredText,
|
||||
final Project project,
|
||||
final Component component,
|
||||
@NotNull final AnActionEvent e) {
|
||||
@Nullable final AnActionEvent e) {
|
||||
if (element instanceof OptionDescription) {
|
||||
final String configurableId = ((OptionDescription)element).getConfigurableId();
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@@ -108,10 +109,12 @@ public class GotoActionAction extends GotoActionBase implements DumbAware {
|
||||
}
|
||||
final Presentation presentation = action.getTemplatePresentation().clone();
|
||||
final DataContext context = DataManager.getInstance().getDataContext(component);
|
||||
final AnActionEvent event = new AnActionEvent(e.getInputEvent(), context,
|
||||
e.getPlace(), presentation,
|
||||
final AnActionEvent event = new AnActionEvent(e == null ? null : e.getInputEvent(),
|
||||
context,
|
||||
e == null ? ActionPlaces.UNKNOWN : e.getPlace(),
|
||||
presentation,
|
||||
ActionManager.getInstance(),
|
||||
e.getModifiers());
|
||||
e == null ? 0 : e.getModifiers());
|
||||
|
||||
if (ActionUtil.lastUpdateAndCheckDumb(action, event, true)) {
|
||||
if (action instanceof ActionGroup) {
|
||||
|
||||
@@ -336,7 +336,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
|
||||
private void initSearchField(final MySearchTextField search) {
|
||||
final JTextField editor = search.getTextEditor();
|
||||
onFocusLost();
|
||||
// onFocusLost();
|
||||
editor.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
@@ -379,7 +379,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if ( myPopup instanceof AbstractPopup && myPopup.isVisible() && ((AbstractPopup)myPopup).getPopupWindow() == e.getOppositeComponent()) {
|
||||
if ( myPopup instanceof AbstractPopup && myPopup.isVisible()
|
||||
&& ((myList == e.getOppositeComponent()) || ((AbstractPopup)myPopup).getPopupWindow() == e.getOppositeComponent())) {
|
||||
return;
|
||||
}
|
||||
onFocusLost();
|
||||
@@ -491,7 +492,11 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
option.setOptionState(!option.isOptionEnabled());
|
||||
}
|
||||
else {
|
||||
GotoActionAction.openOptionOrPerformAction(value, pattern, project, comp, event);
|
||||
Component c = comp;
|
||||
if (c == null) {
|
||||
c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
}
|
||||
GotoActionAction.openOptionOrPerformAction(value, pattern, project, c, event);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -36,8 +36,9 @@ import java.awt.datatransfer.*;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <p>This class is used to workaround the problem with getting clipboard contents (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4818143).
|
||||
@@ -125,6 +126,7 @@ public class ClipboardSynchronizer implements ApplicationComponent {
|
||||
myClipboardHandler.resetContent();
|
||||
}
|
||||
|
||||
|
||||
private static class ClipboardHandler {
|
||||
public void init() {
|
||||
}
|
||||
@@ -178,6 +180,7 @@ public class ClipboardSynchronizer implements ApplicationComponent {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class MacClipboardHandler extends ClipboardHandler {
|
||||
private Pair<String,Transferable> myFullTransferable;
|
||||
|
||||
@@ -216,7 +219,7 @@ public class ClipboardSynchronizer implements ApplicationComponent {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
myFullTransferable = null;
|
||||
return transferable;
|
||||
}
|
||||
@@ -246,11 +249,11 @@ public class ClipboardSynchronizer implements ApplicationComponent {
|
||||
super.setContent(content, owner);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static Transferable getContentsSafe() {
|
||||
final Ref<Transferable> result = new Ref<Transferable>();
|
||||
|
||||
|
||||
Foundation.executeOnMainThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -263,46 +266,47 @@ public class ClipboardSynchronizer implements ApplicationComponent {
|
||||
|
||||
return result.get();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Transferable getClipboardContentNatively() {
|
||||
String plainText = "public.utf8-plain-text";
|
||||
|
||||
ID pasteboard = Foundation.invoke("NSPasteboard", "generalPasteboard");
|
||||
ID types = Foundation.invoke(pasteboard, "types");
|
||||
IntegerType count = Foundation.invoke(types, "count");
|
||||
@Nullable
|
||||
private static Transferable getClipboardContentNatively() {
|
||||
String plainText = "public.utf8-plain-text";
|
||||
|
||||
ID plainTextType = null;
|
||||
ID pasteboard = Foundation.invoke("NSPasteboard", "generalPasteboard");
|
||||
ID types = Foundation.invoke(pasteboard, "types");
|
||||
IntegerType count = Foundation.invoke(types, "count");
|
||||
|
||||
for (int i = 0; i < count.intValue(); i++) {
|
||||
ID each = Foundation.invoke(types, "objectAtIndex:", i);
|
||||
String eachType = Foundation.toStringViaUTF8(each);
|
||||
if (plainText.equals(eachType)) {
|
||||
plainTextType = each;
|
||||
break;
|
||||
ID plainTextType = null;
|
||||
|
||||
for (int i = 0; i < count.intValue(); i++) {
|
||||
ID each = Foundation.invoke(types, "objectAtIndex:", i);
|
||||
String eachType = Foundation.toStringViaUTF8(each);
|
||||
if (plainText.equals(eachType)) {
|
||||
plainTextType = each;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// will put string value even if we doesn't found java object. this is needed because java caches clipboard value internally and
|
||||
// will reset it ONLY IF we'll put jvm-object into clipboard (see our setContent optimizations which avoids putting jvm-objects
|
||||
// into clipboard)
|
||||
|
||||
Transferable result = null;
|
||||
if (plainTextType != null) {
|
||||
ID text = Foundation.invoke(pasteboard, "stringForType:", plainTextType);
|
||||
String value = Foundation.toStringViaUTF8(text);
|
||||
if (value == null) {
|
||||
LOG.info(String.format("[Clipboard] Strange string value (null?) for type: %s", plainTextType));
|
||||
}
|
||||
else {
|
||||
result = new StringSelection(value);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// will put string value even if we doesn't found java object. this is needed because java caches clipboard value internally and
|
||||
// will reset it ONLY IF we'll put jvm-object into clipboard (see our setContent optimizations which avoids putting jvm-objects
|
||||
// into clipboard)
|
||||
|
||||
Transferable result = null;
|
||||
if (plainTextType != null) {
|
||||
ID text = Foundation.invoke(pasteboard, "stringForType:", plainTextType);
|
||||
String value = Foundation.toStringViaUTF8(text);
|
||||
if (value == null) {
|
||||
LOG.info(String.format("[Clipboard] Strange string value (null?) for type: %s", plainTextType));
|
||||
}
|
||||
else {
|
||||
result = new StringSelection(value);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static class XWinClipboardHandler extends ClipboardHandler {
|
||||
private static final FlavorTable FLAVOR_MAP = (FlavorTable)SystemFlavorMap.getDefaultFlavorMap();
|
||||
|
||||
@@ -328,15 +332,19 @@ public class ClipboardSynchronizer implements ApplicationComponent {
|
||||
}
|
||||
|
||||
try {
|
||||
final Pair<long[], ? extends Collection<DataFlavor>> contents = checkContentsQuick();
|
||||
final Collection<DataFlavor> contents = checkContentsQuick();
|
||||
if (contents != null) {
|
||||
return contents.second.contains(dataFlavor);
|
||||
return contents.contains(dataFlavor);
|
||||
}
|
||||
|
||||
return super.isDataFlavorAvailable(dataFlavor);
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
LOG.warn("Sun bug #6322854", e);
|
||||
LOG.warn("Java bug #6322854", e);
|
||||
return false;
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.warn("Java bug #7173464", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -349,49 +357,20 @@ public class ClipboardSynchronizer implements ApplicationComponent {
|
||||
}
|
||||
|
||||
try {
|
||||
final Pair<long[], ? extends Collection<DataFlavor>> contents = checkContentsQuick();
|
||||
if (contents != null && contents.second.isEmpty()) {
|
||||
final Collection<DataFlavor> contents = checkContentsQuick();
|
||||
if (contents != null && contents.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return super.getContents();
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// todo[r.sh] to remove in IDEA 12.1
|
||||
if (contents != null && "Comparison method violates its general contract!".equals(e.getMessage())) {
|
||||
LOG.error("Cannot sort: " + contents.second + ", atoms: " + atomNames(contents.first), e);
|
||||
return null;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return super.getContents();
|
||||
}
|
||||
catch (NullPointerException e) {
|
||||
LOG.warn("Sun bug #6322854", e);
|
||||
LOG.warn("Java bug #6322854", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> atomNames(long[] formats) {
|
||||
try {
|
||||
Class<?> toolkit = Class.forName("sun.awt.X11.XToolkit");
|
||||
Method getDisplay = toolkit.getDeclaredMethod("getDisplay");
|
||||
getDisplay.setAccessible(true);
|
||||
long display = (Long)getDisplay.invoke(null);
|
||||
|
||||
Class<?> wrapper = Class.forName("sun.awt.X11.XlibWrapper");
|
||||
Method getAtomName = wrapper.getDeclaredMethod("XGetAtomName", long.class, long.class);
|
||||
getAtomName.setAccessible(true);
|
||||
|
||||
List<String> atoms = new ArrayList<String>();
|
||||
for (long format : formats) {
|
||||
String name = (String)getAtomName.invoke(null, display, format);
|
||||
atoms.add(format + ":" + name);
|
||||
}
|
||||
return atoms;
|
||||
}
|
||||
catch (Throwable t) {
|
||||
return Collections.emptyList();
|
||||
catch (IllegalArgumentException e) {
|
||||
LOG.warn("Java bug #7173464", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,7 +392,7 @@ public class ClipboardSynchronizer implements ApplicationComponent {
|
||||
* collection of available data flavors otherwise.
|
||||
*/
|
||||
@Nullable
|
||||
private static Pair<long[], ? extends Collection<DataFlavor>> checkContentsQuick() {
|
||||
private static Collection<DataFlavor> checkContentsQuick() {
|
||||
final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
final Class<? extends Clipboard> aClass = clipboard.getClass();
|
||||
if (!"sun.awt.X11.XClipboard".equals(aClass.getName())) return null;
|
||||
@@ -433,10 +412,10 @@ public class ClipboardSynchronizer implements ApplicationComponent {
|
||||
try {
|
||||
final long[] formats = (long[])getClipboardFormats.invoke(clipboard);
|
||||
if (formats == null || formats.length == 0) {
|
||||
return Pair.create(formats, Collections.<DataFlavor>emptySet());
|
||||
return Collections.emptySet();
|
||||
}
|
||||
@SuppressWarnings({"unchecked"}) final Set<DataFlavor> set = DataTransferer.getInstance().getFlavorsForFormats(formats, FLAVOR_MAP).keySet();
|
||||
return Pair.create(formats, set);
|
||||
return set;
|
||||
}
|
||||
catch (IllegalAccessException ignore) { }
|
||||
catch (IllegalArgumentException ignore) { }
|
||||
@@ -454,6 +433,7 @@ public class ClipboardSynchronizer implements ApplicationComponent {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class HeadlessClipboardHandler extends ClipboardHandler {
|
||||
private volatile Transferable myContent = null;
|
||||
|
||||
|
||||
@@ -5009,6 +5009,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myDropHandler = dropHandler;
|
||||
}
|
||||
|
||||
|
||||
private static class MyInputMethodHandleSwingThreadWrapper implements InputMethodRequests {
|
||||
private final InputMethodRequests myDelegate;
|
||||
|
||||
@@ -5018,114 +5019,53 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
@Override
|
||||
public Rectangle getTextLocation(final TextHitInfo offset) {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) return myDelegate.getTextLocation(offset);
|
||||
|
||||
final Rectangle[] r = new Rectangle[1];
|
||||
try {
|
||||
GuiUtils.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
r[0] = myDelegate.getTextLocation(offset);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return r[0];
|
||||
return execute(new Computable<Rectangle>() {
|
||||
@Override
|
||||
public Rectangle compute() {
|
||||
return myDelegate.getTextLocation(offset);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextHitInfo getLocationOffset(final int x, final int y) {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) return myDelegate.getLocationOffset(x, y);
|
||||
|
||||
final TextHitInfo[] r = new TextHitInfo[1];
|
||||
try {
|
||||
GuiUtils.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
r[0] = myDelegate.getLocationOffset(x, y);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return r[0];
|
||||
return execute(new Computable<TextHitInfo>() {
|
||||
@Override
|
||||
public TextHitInfo compute() {
|
||||
return myDelegate.getLocationOffset(x, y);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInsertPositionOffset() {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) return myDelegate.getInsertPositionOffset();
|
||||
|
||||
final int[] r = new int[1];
|
||||
try {
|
||||
GuiUtils.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
r[0] = myDelegate.getInsertPositionOffset();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return r[0];
|
||||
return execute(new Computable<Integer>() {
|
||||
@Override
|
||||
public Integer compute() {
|
||||
return myDelegate.getInsertPositionOffset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributedCharacterIterator getCommittedText(final int beginIndex,
|
||||
final int endIndex,
|
||||
public AttributedCharacterIterator getCommittedText(final int beginIndex, final int endIndex,
|
||||
final AttributedCharacterIterator.Attribute[] attributes) {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
return myDelegate.getCommittedText(beginIndex, endIndex, attributes);
|
||||
}
|
||||
final AttributedCharacterIterator[] r = new AttributedCharacterIterator[1];
|
||||
try {
|
||||
GuiUtils.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
r[0] = myDelegate.getCommittedText(beginIndex, endIndex, attributes);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return r[0];
|
||||
return execute(new Computable<AttributedCharacterIterator>() {
|
||||
@Override
|
||||
public AttributedCharacterIterator compute() {
|
||||
return myDelegate.getCommittedText(beginIndex, endIndex, attributes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCommittedTextLength() {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) return myDelegate.getCommittedTextLength();
|
||||
final int[] r = new int[1];
|
||||
try {
|
||||
GuiUtils.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
r[0] = myDelegate.getCommittedTextLength();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return r[0];
|
||||
return execute(new Computable<Integer>() {
|
||||
@Override
|
||||
public Integer compute() {
|
||||
return myDelegate.getCommittedTextLength();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -5136,27 +5076,40 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
@Override
|
||||
public AttributedCharacterIterator getSelectedText(final AttributedCharacterIterator.Attribute[] attributes) {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) return myDelegate.getSelectedText(attributes);
|
||||
return execute(new Computable<AttributedCharacterIterator>() {
|
||||
@Override
|
||||
public AttributedCharacterIterator compute() {
|
||||
return myDelegate.getSelectedText(attributes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final AttributedCharacterIterator[] r = new AttributedCharacterIterator[1];
|
||||
try {
|
||||
GuiUtils.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
r[0] = myDelegate.getSelectedText(attributes);
|
||||
}
|
||||
});
|
||||
private static <T> T execute(final Computable<T> computable) {
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
return computable.compute();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.error(e);
|
||||
else {
|
||||
final Ref<T> ref = Ref.create();
|
||||
try {
|
||||
GuiUtils.invokeAndWait(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ref.set(computable.compute());
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return ref.get();
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
return r[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class MyInputMethodHandler implements InputMethodRequests {
|
||||
private String composedText;
|
||||
private ProperTextRange composedTextRange;
|
||||
@@ -5357,8 +5310,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
}
|
||||
}
|
||||
|
||||
private class MyMouseAdapter extends MouseAdapter {
|
||||
|
||||
private class MyMouseAdapter extends MouseAdapter {
|
||||
private boolean mySelectionTweaked;
|
||||
|
||||
@Override
|
||||
@@ -6160,14 +6113,14 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
@Override
|
||||
public void updateStarted(@NotNull Document doc) {
|
||||
if (doc != getDocument()) return;
|
||||
|
||||
|
||||
bulkUpdateStarted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFinished(@NotNull Document doc) {
|
||||
if (doc != getDocument()) return;
|
||||
|
||||
|
||||
bulkUpdateFinished();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.intellij.vcs.log.Hash;
|
||||
import com.intellij.vcs.log.VcsCommit;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -26,7 +27,7 @@ public class VcsCommitImpl implements VcsCommit {
|
||||
|
||||
public VcsCommitImpl(@NotNull Hash hash, @NotNull List<Hash> parents) {
|
||||
myHash = hash;
|
||||
myParents = parents;
|
||||
myParents = new ArrayList<Hash>(parents);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -39,7 +39,7 @@ import java.util.Set;
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public class VcsLogManager {
|
||||
public class VcsLogManager implements Disposable {
|
||||
|
||||
public static final ExtensionPointName<VcsLogProvider> LOG_PROVIDER_EP = ExtensionPointName.create("com.intellij.logProvider");
|
||||
|
||||
@@ -61,6 +61,7 @@ public class VcsLogManager {
|
||||
myLogObjectsFactory = logObjectsFactory;
|
||||
mySettings = settings;
|
||||
myUiProperties = uiProperties;
|
||||
Disposer.register(myProject, this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -71,6 +72,7 @@ public class VcsLogManager {
|
||||
VcsLogDataHolder.init(myProject, myLogObjectsFactory, logProviders, mySettings, new Consumer<VcsLogDataHolder>() {
|
||||
@Override
|
||||
public void consume(VcsLogDataHolder vcsLogDataHolder) {
|
||||
Disposer.register(VcsLogManager.this, vcsLogDataHolder);
|
||||
VcsLogUI logUI = new VcsLogUI(vcsLogDataHolder, myProject, mySettings,
|
||||
new VcsLogColorManagerImpl(logProviders.keySet()), myUiProperties);
|
||||
myLogDataHolder = vcsLogDataHolder;
|
||||
@@ -119,6 +121,10 @@ public class VcsLogManager {
|
||||
return myUi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
private static class VcsLogContainer extends JPanel {
|
||||
|
||||
private final JBLoadingPanel myLoadingPanel;
|
||||
|
||||
@@ -165,8 +165,14 @@ class DetailsPanel extends JPanel implements ListSelectionListener {
|
||||
|
||||
String authorText = commit.getAuthorName() + " at " + DateFormatUtil.formatDateTime(commit.getAuthorTime());
|
||||
if (!commit.getAuthorName().equals(commit.getCommitterName()) || !commit.getAuthorEmail().equals(commit.getCommitterEmail())) {
|
||||
authorText += " (committed by " + commit.getCommitterName() +
|
||||
" at " + DateFormatUtil.formatDateTime(commit.getCommitTime()) + ")";
|
||||
String commitTime;
|
||||
if (commit.getCommitTime() != commit.getAuthorTime()) {
|
||||
commitTime = " at " + DateFormatUtil.formatDateTime(commit.getCommitTime());
|
||||
}
|
||||
else {
|
||||
commitTime = "";
|
||||
}
|
||||
authorText += " (committed by " + commit.getCommitterName() + commitTime + ")";
|
||||
}
|
||||
myAuthor.setText(authorText);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static git4idea.history.GitLogParser.GitLogOption.*;
|
||||
@@ -535,8 +536,10 @@ public class GitHistoryUtils {
|
||||
|
||||
@NotNull
|
||||
public static List<TimedVcsCommit> readAllHashes(@NotNull Project project, @NotNull VirtualFile root) throws VcsException {
|
||||
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
|
||||
GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.NONE, HASH, PARENTS, AUTHOR_TIME);
|
||||
final int COMMIT_BUFFER = 1000;
|
||||
|
||||
GitLineHandler h = new GitLineHandler(project, root, GitCommand.LOG);
|
||||
final GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.NONE, HASH, PARENTS, AUTHOR_TIME);
|
||||
h.setStdoutSuppressed(true);
|
||||
h.addParameters(parser.getPretty(), "--encoding=UTF-8");
|
||||
h.addParameters("HEAD", "--branches", "--remotes", "--tags");
|
||||
@@ -544,21 +547,82 @@ public class GitHistoryUtils {
|
||||
h.addParameters("--date-order");
|
||||
h.endOptions();
|
||||
|
||||
String output = h.run();
|
||||
final List<TimedVcsCommit> commits = ContainerUtil.newArrayList();
|
||||
|
||||
List<GitLogRecord> records = parser.parse(output);
|
||||
|
||||
return ContainerUtil.map(records, new Function<GitLogRecord, TimedVcsCommit>() {
|
||||
final StringBuilder record = new StringBuilder();
|
||||
final AtomicInteger records = new AtomicInteger();
|
||||
final Ref<VcsException> ex = new Ref<VcsException>();
|
||||
h.addLineListener(new GitLineHandlerListener() {
|
||||
@Override
|
||||
public TimedVcsCommit fun(GitLogRecord record) {
|
||||
List<Hash> parents = new SmartList<Hash>();
|
||||
for (String parent : record.getParentsHashes()) {
|
||||
parents.add(HashImpl.build(parent));
|
||||
public void onLineAvailable(String line, Key outputType) {
|
||||
try {
|
||||
int recordEnd = line.indexOf(GitLogParser.RECORD_END);
|
||||
String afterParseRemainder;
|
||||
if (recordEnd == line.length() - 1) { // ends with
|
||||
record.append(line);
|
||||
afterParseRemainder = "";
|
||||
}
|
||||
else if (recordEnd == -1) { // record doesn't end on this line => just appending, no parsing
|
||||
record.append(line);
|
||||
afterParseRemainder = null;
|
||||
}
|
||||
else { // record ends in the middle of this line
|
||||
record.append(line.substring(0, recordEnd + 1));
|
||||
afterParseRemainder = line.substring(recordEnd + 1);
|
||||
}
|
||||
if (afterParseRemainder != null && records.incrementAndGet() > COMMIT_BUFFER) { // null means can't parse now
|
||||
commits.addAll(parseCommit(parser, record));
|
||||
record.setLength(0);
|
||||
record.append(afterParseRemainder);
|
||||
}
|
||||
}
|
||||
return ServiceManager.getService(VcsLogObjectsFactory.class).createTimedCommit(HashImpl.build(record.getHash()),
|
||||
parents, record.getAuthorTimeStamp());
|
||||
catch (Exception e) {
|
||||
ex.set(new VcsException(e));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTerminated(int exitCode) {
|
||||
try {
|
||||
commits.addAll(parseCommit(parser, record));
|
||||
}
|
||||
catch (Exception e) {
|
||||
ex.set(new VcsException(e));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startFailed(Throwable exception) {
|
||||
ex.set(new VcsException(exception));
|
||||
}
|
||||
});
|
||||
h.runInCurrentThread(null);
|
||||
if (!ex.isNull()) {
|
||||
throw ex.get();
|
||||
}
|
||||
return commits;
|
||||
}
|
||||
|
||||
private static List<TimedVcsCommit> parseCommit(GitLogParser parser, StringBuilder record) {
|
||||
List<GitLogRecord> rec = parser.parse(record.toString());
|
||||
return ContainerUtil.mapNotNull(rec, new Function<GitLogRecord, TimedVcsCommit>() {
|
||||
@Override
|
||||
public TimedVcsCommit fun(GitLogRecord record) {
|
||||
return record == null ? null : convert(record);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static TimedVcsCommit convert(GitLogRecord rec) {
|
||||
VcsLogObjectsFactory factory = ServiceManager.getService(VcsLogObjectsFactory.class);
|
||||
List<Hash> parents = ContainerUtil.map(rec.getParentsHashes(), new Function<String, Hash>() {
|
||||
@Override
|
||||
public Hash fun(String s) {
|
||||
return HashImpl.build(s);
|
||||
}
|
||||
});
|
||||
return factory.createTimedCommit(HashImpl.build(rec.getHash()), parents, rec.getAuthorTimeStamp());
|
||||
}
|
||||
|
||||
private static class MyTokenAccumulator {
|
||||
|
||||
@@ -361,6 +361,7 @@ prepended
|
||||
prepends
|
||||
preprocessor
|
||||
preprocessors
|
||||
println
|
||||
processlist
|
||||
profiler
|
||||
progressbar
|
||||
|
||||
Reference in New Issue
Block a user