diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy index 16ca708560a6..ab9ea13a425d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/HippieCompletionTest.groovy @@ -113,6 +113,21 @@ class Foo { ''' } + public void "test complete variable name in string literal"() { + myFixture.configureByText "a.java", ''' +class Xoo { + String foobar = "foo"; +} +''' + complete() + myFixture.checkResult ''' +class Xoo { + String foobar = "foobar"; +} +''' + + } + private void complete() { myFixture.performEditorAction(IdeActions.ACTION_HIPPIE_COMPLETION) } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java index 4f273bb1cb90..19d4804efbe5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java @@ -44,7 +44,6 @@ import java.util.*; */ public class HippieWordCompletionHandler implements CodeInsightActionHandler { private static final Key KEY_STATE = new Key("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(); diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java index d6eccc0858b8..6aef4e82f420 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java @@ -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) { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index 89e2b11b4b75..c63edeb988c6 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -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); } } }); diff --git a/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java b/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java index e18c79a76b42..d46b868f8d02 100644 --- a/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java +++ b/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java @@ -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; /** *

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 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 result = new Ref(); - + 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> contents = checkContentsQuick(); + final Collection 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> contents = checkContentsQuick(); - if (contents != null && contents.second.isEmpty()) { + final Collection 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 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 atoms = new ArrayList(); - 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> checkContentsQuick() { + private static Collection checkContentsQuick() { final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); final Class 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.emptySet()); + return Collections.emptySet(); } @SuppressWarnings({"unchecked"}) final Set 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; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index b73092aa3fb9..99f54696be4e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -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() { + @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() { + @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() { + @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() { + @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() { + @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() { + @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 execute(final Computable computable) { + if (ApplicationManager.getApplication().isDispatchThread()) { + return computable.compute(); } - catch (InterruptedException e) { - LOG.error(e); + else { + final Ref 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(); } } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsCommitImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsCommitImpl.java index e1f075b014cd..3900dfc43c28 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsCommitImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsCommitImpl.java @@ -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 parents) { myHash = hash; - myParents = parents; + myParents = new ArrayList(parents); } @Override diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java index 5e7a0a809835..ab2eeccd5164 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogManager.java @@ -39,7 +39,7 @@ import java.util.Set; /** * @author Kirill Likhodedov */ -public class VcsLogManager { +public class VcsLogManager implements Disposable { public static final ExtensionPointName 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() { @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; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java index 22346edecdcd..c9fe1021e547 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java @@ -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); } diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index 79f7223bc1ea..d51f4765abce 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -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 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 commits = ContainerUtil.newArrayList(); - List records = parser.parse(output); - - return ContainerUtil.map(records, new Function() { + final StringBuilder record = new StringBuilder(); + final AtomicInteger records = new AtomicInteger(); + final Ref ex = new Ref(); + h.addLineListener(new GitLineHandlerListener() { @Override - public TimedVcsCommit fun(GitLogRecord record) { - List parents = new SmartList(); - 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 parseCommit(GitLogParser parser, StringBuilder record) { + List rec = parser.parse(record.toString()); + return ContainerUtil.mapNotNull(rec, new Function() { + @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 parents = ContainerUtil.map(rec.getParentsHashes(), new Function() { + @Override + public Hash fun(String s) { + return HashImpl.build(s); + } + }); + return factory.createTimedCommit(HashImpl.build(rec.getHash()), parents, rec.getAuthorTimeStamp()); } private static class MyTokenAccumulator { diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic index 5db0eb8ee39e..637ca7510b83 100644 --- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic +++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic @@ -361,6 +361,7 @@ prepended prepends preprocessor preprocessors +println processlist profiler progressbar