diff --git a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java index edd7adbe0c71..98930c82224c 100644 --- a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java +++ b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java @@ -227,7 +227,7 @@ public abstract class QuickFixFactory { public abstract IntentionAction createCreateAnnotationMethodFromUsageFix(@NotNull PsiNameValuePair pair); @NotNull - public abstract IntentionAction createOptimizeImportsFix(); + public abstract IntentionAction createOptimizeImportsFix(boolean onTheFly); public abstract void registerFixesForUnusedParameter(@NotNull PsiParameter parameter, @NotNull Object highlightInfo); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java index 83bec198cd1f..df9176e8840f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java @@ -187,7 +187,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass private void optimizeImportsOnTheFly(@NotNull final Editor editor) { if (myHasRedundantImports || myHasMissortedImports) { - IntentionAction optimizeImportsFix = QuickFixFactory.getInstance().createOptimizeImportsFix(); + IntentionAction optimizeImportsFix = QuickFixFactory.getInstance().createOptimizeImportsFix(true); if (optimizeImportsFix.isAvailable(myProject, editor, myFile) && myFile.isWritable()) { optimizeImportsFix.invoke(myProject, editor, myFile); } @@ -793,7 +793,7 @@ public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT).range(importStatement).descriptionAndTooltip(description) .create(); - QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createOptimizeImportsFix(), unusedImportKey); + QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createOptimizeImportsFix(false), unusedImportKey); QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createEnableOptimizeImportsOnTheFlyFix(), unusedImportKey); myHasRedundantImports = true; return info; diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java index 0bc9f2999f4b..768341918c81 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java @@ -600,7 +600,7 @@ public class QuickFixFactoryImpl extends QuickFixFactory { @NotNull @Override - public IntentionAction createOptimizeImportsFix() { + public IntentionAction createOptimizeImportsFix(final boolean onTheFly) { final OptimizeImportsFix fix = new OptimizeImportsFix(); return new IntentionAction() { @@ -618,7 +618,7 @@ public class QuickFixFactoryImpl extends QuickFixFactory { @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return timeToOptimizeImports(file) && fix.isAvailable(project, editor, file); + return (!onTheFly || timeToOptimizeImports(file)) && fix.isAvailable(project, editor, file); } @Override diff --git a/lib/src/trove4j_src.jar b/lib/src/trove4j_src.jar index b1dd8e4b3bae..2d0f5650c3a6 100644 Binary files a/lib/src/trove4j_src.jar and b/lib/src/trove4j_src.jar differ diff --git a/lib/trove4j.jar b/lib/trove4j.jar index cf5fee9ef2d6..71a04028f785 100644 Binary files a/lib/trove4j.jar and b/lib/trove4j.jar differ diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java index b50395009c34..2f4aa4198f85 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/QuickEditHandler.java @@ -124,7 +124,8 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable { myNewVirtualFile.setOriginalFile(origFile.getVirtualFile()); assert myNewFile != null : "PSI file is null"; - assert myNewFile.getTextLength() == myNewVirtualFile.getLength() : "PSI / Virtual file text mismatch"; + assert myNewFile.getTextLength() == myNewVirtualFile.getContent().length() : "PSI / Virtual file text mismatch"; + myNewVirtualFile.setOriginalFile(origFile.getVirtualFile()); // suppress possible errors as in injected mode myNewFile.putUserData(InjectedLanguageUtil.FRANKENSTEIN_INJECTION, diff --git a/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java b/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java index d91772fc8813..ada5574975f5 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java @@ -182,7 +182,7 @@ class EventLogConsole { lineColors.add(lineHighlighter); } - myProjectModel.removeHandlers.put(notification, new Runnable() { + final Runnable removeHandler = new Runnable() { @Override public void run() { for (RangeHighlighter color : lineColors) { @@ -202,7 +202,13 @@ class EventLogConsole { } } } - }); + }; + if (!notification.isExpired()) { + myProjectModel.removeHandlers.put(notification, removeHandler); + } + else { + removeHandler.run(); + } } public Editor getConsoleEditor() { diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsCommitMetadata.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsCommitMetadata.java new file mode 100644 index 000000000000..5faa8e7870f1 --- /dev/null +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsCommitMetadata.java @@ -0,0 +1,25 @@ +package com.intellij.vcs.log; + +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + *

Full details of a commit: all metadata (commit message, author, committer, etc.) but without changes.

+ *

These details will be shown in dedicated panels displayed near the log, and can be used for in-memory filtering.

+ *

An instance of this object can be obtained via + * {@link VcsLogObjectsFactory#createCommitMetadata(Hash, List, long, VirtualFile, String, String, String, String, String, String,long) + * VcsLogObjectsFactory#createMediumDetails}

+ */ +public interface VcsCommitMetadata extends VcsShortCommitDetails { + + @NotNull + String getFullMessage(); + + @NotNull + VcsUser getCommitter(); + + long getAuthorTime(); + +} diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsFullCommitDetails.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsFullCommitDetails.java index 1b9757abc1ea..d5c0b60091ea 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsFullCommitDetails.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsFullCommitDetails.java @@ -1,32 +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.vcs.changes.Change; -import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import java.util.Collection; -import java.util.List; /** - *

Full details of a commit: all metadata (commit message, author, committer, etc.) and the changes.

- *

These details will be shown in dedicated panels displayed near the log.

- *

An instance of this object can be obtained via - * {@link VcsLogObjectsFactory#createFullDetails(Hash, List, long, VirtualFile, String, String, String, String, String, String, long, - * List, ContentRevisionFactory) VcsLogObjectsFactory#createFullDetails}

- * - * @author Kirill Likhodedov + * All metadata + changes. */ -public interface VcsFullCommitDetails extends VcsShortCommitDetails { - - @NotNull - String getFullMessage(); +public interface VcsFullCommitDetails extends VcsCommitMetadata { @NotNull Collection getChanges(); - @NotNull - VcsUser getCommitter(); - - long getAuthorTime(); - } diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDetailsFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDetailsFilter.java index 31ce3d40a37c..838e95c306b4 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDetailsFilter.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDetailsFilter.java @@ -3,12 +3,12 @@ package com.intellij.vcs.log; import org.jetbrains.annotations.NotNull; /** - * Filter which needs {@link VcsFullCommitDetails} to work. + * Filter which needs {@link VcsCommitMetadata} to work. * * @see VcsLogGraphFilter */ public interface VcsLogDetailsFilter extends VcsLogFilter { - boolean matches(@NotNull VcsFullCommitDetails details); + boolean matches(@NotNull VcsCommitMetadata details); } diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogObjectsFactory.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogObjectsFactory.java index ddccc05ce778..387e64901578 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogObjectsFactory.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogObjectsFactory.java @@ -1,9 +1,11 @@ package com.intellij.vcs.log; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; +import java.util.Collection; import java.util.List; /** @@ -26,13 +28,18 @@ public interface VcsLogObjectsFactory { VcsShortCommitDetails createShortDetails(@NotNull Hash hash, @NotNull List parents, long timeStamp, VirtualFile root, @NotNull String subject, @NotNull String authorName, String authorEmail); + @NotNull + VcsCommitMetadata createCommitMetadata(@NotNull Hash hash, @NotNull List parents, long time, VirtualFile root, + @NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, + @NotNull String message, @NotNull String committerName, @NotNull String committerEmail, + long authorTime); + @NotNull VcsFullCommitDetails createFullDetails(@NotNull Hash hash, @NotNull List parents, long time, VirtualFile root, - @NotNull String subject, - @NotNull String authorName, @NotNull String authorEmail, @NotNull String message, - @NotNull String committerName, - @NotNull String committerEmail, long authorTime, @NotNull List changes, - @NotNull ContentRevisionFactory contentRevisionFactory); + @NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, + @NotNull String message, @NotNull String committerName, @NotNull String committerEmail, + long authorTime, + @NotNull ThrowableComputable, ? extends Exception> changesGetter); @NotNull VcsUser createUser(@NotNull String name, @NotNull String email); diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java index 3565dfd3fa4d..d8774b46a98e 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java @@ -22,7 +22,7 @@ public interface VcsLogProvider { * Reads the given number of the most recent commits from the log. */ @NotNull - List readFirstBlock(@NotNull VirtualFile root, boolean ordered, int commitCount) throws VcsException; + List readFirstBlock(@NotNull VirtualFile root, boolean ordered, int commitCount) throws VcsException; /** *

Reads the whole history, but only hashes & parents.

diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java index 4afa5f19028a..65c3ab7f1dbe 100644 --- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java +++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsShortCommitDetails.java @@ -11,11 +11,12 @@ import java.util.List; *

These details will be displayed in the log table.

* *

An instance of this object can be obtained via - * {@link VcsLogObjectsFactory#createShortDetails(Hash, List, long, VirtualFile, String, String, String) VcsLogObjectsFactory#createShortDetails} + * {@link VcsLogObjectsFactory#createShortDetails(Hash, List, long, VirtualFile, String, String, String) + * VcsLogObjectsFactory#createShortDetails} *

* + * @see VcsCommitMetadata * @see VcsFullCommitDetails - * @author Kirill Likhodedov */ public interface VcsShortCommitDetails { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/CommitDetailsGetter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/CommitDetailsGetter.java index 92dca3e276b2..9907051c5a48 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/CommitDetailsGetter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/CommitDetailsGetter.java @@ -2,17 +2,17 @@ package com.intellij.vcs.log.data; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLogProvider; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; /** * The CommitDetailsGetter is responsible for getting {@link VcsFullCommitDetails complete commit details} from the cache or from the VCS. - * - * @author Kirill Likhodedov */ public class CommitDetailsGetter extends DataGetter { @@ -20,6 +20,12 @@ public class CommitDetailsGetter extends DataGetter { super(dataHolder, logProviders, new VcsCommitCache()); } + @Nullable + @Override + protected VcsFullCommitDetails getFromAdditionalCache(@NotNull Hash hash) { + return null; + } + @NotNull @Override protected List readDetails(@NotNull VcsLogProvider logProvider, @NotNull VirtualFile root, diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java index f410c72fbf27..64c4f1563fee 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataGetter.java @@ -81,7 +81,7 @@ public abstract class DataGetter implements Dis } @Nullable - public T getCommitData(int row, @NotNull AbstractVcsLogTableModel tableModel) { + public T getCommitData(int row, @NotNull AbstractVcsLogTableModel tableModel) { assert EventQueue.isDispatchThread(); Hash hash = tableModel.getHashAtRow(row); if (hash == null) { @@ -113,10 +113,16 @@ public abstract class DataGetter implements Dis } return details; } - return (T)myDataHolder.getTopCommitDetails(hash); + return getFromAdditionalCache(hash); } - private void runLoadAroundCommitData(int row, @NotNull AbstractVcsLogTableModel tableModel) { + /** + * Lookup somewhere else but the standard cache. + */ + @Nullable + protected abstract T getFromAdditionalCache(@NotNull Hash hash); + + private void runLoadAroundCommitData(int row, @NotNull AbstractVcsLogTableModel tableModel) { long taskNumber = myCurrentTaskIndex++; MultiMap commits = getCommitsAround(row, tableModel, UP_PRELOAD_COUNT, DOWN_PRELOAD_COUNT); for (Map.Entry> hashesByRoots : commits.entrySet()) { @@ -137,9 +143,8 @@ public abstract class DataGetter implements Dis } @NotNull - private static MultiMap getCommitsAround(int selectedRow, - @NotNull AbstractVcsLogTableModel model, - int above, int below) { + private static MultiMap getCommitsAround(int selectedRow, @NotNull AbstractVcsLogTableModel model, + int above, int below) { MultiMap commits = MultiMap.create(); for (int row = Math.max(0, selectedRow - above); row < selectedRow + below && row < model.getRowCount(); row++) { Hash hash = model.getHashAtRow(row); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/LoadingDetails.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/LoadingDetails.java index e0fab7232f40..1848cf03aec9 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/LoadingDetails.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/LoadingDetails.java @@ -1,26 +1,23 @@ package com.intellij.vcs.log.data; -import com.intellij.openapi.vcs.FilePathImpl; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vcs.changes.SimpleContentRevision; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.vcs.log.ContentRevisionFactory; import com.intellij.vcs.log.Hash; -import com.intellij.vcs.log.impl.VcsFullCommitDetailsImpl; +import com.intellij.vcs.log.impl.VcsChangesLazilyParsedDetails; import com.intellij.vcs.log.impl.VcsUserImpl; import org.jetbrains.annotations.NotNull; -import java.io.File; +import java.util.Collection; import java.util.Collections; /** - * Fake {@link VcsFullCommitDetailsImpl} implementation that is used to indicate that details are not ready for the moment, + * Fake {@link com.intellij.vcs.log.impl.VcsCommitMetadataImpl} implementation that is used to indicate that details are not ready for the moment, * they are being retrieved from the VCS. * * @author Kirill Likhodedov */ -public class LoadingDetails extends VcsFullCommitDetailsImpl { +public class LoadingDetails extends VcsChangesLazilyParsedDetails { private static final VcsUserImpl STUB_USER = new VcsUserImpl("", ""); @@ -28,19 +25,12 @@ public class LoadingDetails extends VcsFullCommitDetailsImpl { public LoadingDetails(@NotNull Hash hash, long loadingTaskIndex, @NotNull VirtualFile root) { super(hash, Collections.emptyList(), -1, root, "Loading...", STUB_USER, "", STUB_USER, -1, - Collections.emptyList(), new ContentRevisionFactory() { - @NotNull - @Override - public ContentRevision createRevision(@NotNull VirtualFile file, @NotNull Hash hash) { - return new SimpleContentRevision("", new FilePathImpl(file), hash.asString()); - } - - @NotNull - @Override - public ContentRevision createRevision(@NotNull VirtualFile root, @NotNull String path, @NotNull Hash hash) { - return new SimpleContentRevision("", new FilePathImpl(new File(path), false), hash.asString()); - } - }); + new ThrowableComputable, Exception>() { + @Override + public Collection compute() throws Exception { + return Collections.emptyList(); + } + }); myLoadingTaskIndex = loadingTaskIndex; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/MiniDetailsGetter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/MiniDetailsGetter.java index 2ca21ef36770..0dceb75b6a6c 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/MiniDetailsGetter.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/MiniDetailsGetter.java @@ -2,22 +2,27 @@ package com.intellij.vcs.log.data; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.vcs.log.Hash; import com.intellij.vcs.log.VcsLogProvider; import com.intellij.vcs.log.VcsShortCommitDetails; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; -/** - * @author Kirill Likhodedov - */ public class MiniDetailsGetter extends DataGetter { MiniDetailsGetter(@NotNull VcsLogDataHolder dataHolder, @NotNull Map logProviders) { super(dataHolder, logProviders, new VcsCommitCache()); } + @Nullable + @Override + protected VcsShortCommitDetails getFromAdditionalCache(@NotNull Hash hash) { + return myDataHolder.getTopCommitDetails(hash); + } + @NotNull @Override protected List readDetails(@NotNull VcsLogProvider logProvider, @NotNull VirtualFile root, diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java index ffcb27f76621..913ff526305a 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java @@ -127,7 +127,7 @@ public class VcsLogDataHolder implements Disposable, VcsLogDataProvider { * which is important because these details will be constantly visible to the user, * thus it would be annoying to re-load them from VCS if the cache overflows. */ - @NotNull private final Map myTopCommitsDetailsCache = ContainerUtil.newConcurrentMap(); + @NotNull private final Map myTopCommitsDetailsCache = ContainerUtil.newConcurrentMap(); /** * Checks if "load more commit details" process is already in progress to avoid scheduling multiple similar processes. @@ -488,7 +488,7 @@ public class VcsLogDataHolder implements Disposable, VcsLogDataProvider { boolean orderedForRepo = ordered && !logProvider.supportsFastUnorderedCommits(); // will order manually int commitCountForRepo = orderedForRepo ? commitsCount : commitsCount * 2; // but need to request more commits - List firstBlockDetails = logProvider.readFirstBlock(root, orderedForRepo, commitCountForRepo); + List firstBlockDetails = logProvider.readFirstBlock(root, orderedForRepo, commitCountForRepo); sw.report(); sw = StopWatch.start("readAllRefs for" + root.getName()); Collection newRefs = logProvider.readAllRefs(root); @@ -503,8 +503,8 @@ public class VcsLogDataHolder implements Disposable, VcsLogDataProvider { return infoByRoot.entrySet(); } - private void storeUsers(@NotNull List details) { - for (VcsFullCommitDetails detail : details) { + private void storeUsers(@NotNull List details) { + for (VcsCommitMetadata detail : details) { myUserRegistry.addUser(detail.getAuthor()); myUserRegistry.addUser(detail.getCommitter()); } @@ -634,18 +634,18 @@ public class VcsLogDataHolder implements Disposable, VcsLogDataProvider { }); } - private void storeTopCommitsDetailsInCache(List firstBlockDetails) { + private void storeTopCommitsDetailsInCache(List firstBlockDetails) { // some commits may be no longer available (e.g. rewritten after rebase), but let them stay in the cache: // they won't occupy too much place, while checking & removing them is not easy. - for (VcsFullCommitDetails detail : firstBlockDetails) { + for (VcsCommitMetadata detail : firstBlockDetails) { myTopCommitsDetailsCache.put(detail.getHash(), detail); } } - private List getCommitsFromDetails(List firstBlockDetails) { - List commits = ContainerUtil.map(firstBlockDetails, new Function() { + private List getCommitsFromDetails(List firstBlockDetails) { + List commits = ContainerUtil.map(firstBlockDetails, new Function() { @Override - public TimedVcsCommit fun(VcsFullCommitDetails details) { + public TimedVcsCommit fun(VcsCommitMetadata details) { return new CompactCommit(details.getHash(), details.getParents(), details.getTime()); } }); @@ -724,7 +724,7 @@ public class VcsLogDataHolder implements Disposable, VcsLogDataProvider { } @Nullable - public VcsFullCommitDetails getTopCommitDetails(@NotNull Hash hash) { + public VcsCommitMetadata getTopCommitDetails(@NotNull Hash hash) { return myTopCommitsDetailsCache.get(hash); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java index 439f319c4cd6..8e29f28ee8ab 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java @@ -15,7 +15,7 @@ */ package com.intellij.vcs.log.data; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsCommitMetadata; import com.intellij.vcs.log.VcsLogDateFilter; import com.intellij.vcs.log.VcsLogDetailsFilter; import org.jetbrains.annotations.NotNull; @@ -34,7 +34,7 @@ public class VcsLogDateFilterImpl implements VcsLogDateFilter, VcsLogDetailsFilt } @Override - public boolean matches(@NotNull VcsFullCommitDetails details) { + public boolean matches(@NotNull VcsCommitMetadata details) { Date date = new Date(details.getTime()); // Git itself also filters by commit time, not author time boolean matches = true; if (myAfter != null) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java index c8d276872d34..ddc37fd83e36 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java @@ -49,7 +49,7 @@ public class VcsLogFilterer { private AbstractVcsLogTableModel applyDetailsFilter(DataPack dataPack, List detailsFilters) { if (!detailsFilters.isEmpty()) { - List filteredCommits = filterByDetails(dataPack, detailsFilters); + List filteredCommits = filterInMemory(dataPack, detailsFilters); if (filteredCommits.isEmpty()) { return new EmptyTableModel(dataPack, myLogDataHolder, myUI, LoadMoreStage.INITIAL); } @@ -154,44 +154,42 @@ public class VcsLogFilterer { } @NotNull - private List filterByDetails(@NotNull DataPack dataPack, @NotNull List detailsFilters) { + private List filterInMemory(@NotNull DataPack dataPack, @NotNull List detailsFilters) { List result = ContainerUtil.newArrayList(); - int topCommits = myLogDataHolder.getSettings().getRecentCommitsCount(); - List visibleCommits = VcsLogUtil.getVisibleCommits(dataPack.getGraphFacade()); - for (int i = 0; i < topCommits && i < visibleCommits.size(); i++) { - int commitIndex = visibleCommits.get(i); - final VcsFullCommitDetails details = getDetailsFromCache(commitIndex); - if (details == null) { - // Details for recent commits should be available in the cache. - // However if they are not there for some reason, we stop filtering. - // If we continue, if this commit without details matches filters, - // if details of an older commit are found in the cache, and if this older commit matches the filter, - // then we will return the list which incorrectly misses some matching commit in the middle. - // => Instead we rather will return a smaller list: this is not a problem, - // because the VCS will be requested for filtered details if there are not enough of them. - LOG.debug("No details found for a recent commit " + myLogDataHolder.getHash(commitIndex)); + for (int visibleCommit : VcsLogUtil.getVisibleCommits(dataPack.getGraphFacade())) { + VcsCommitMetadata data = getDetailsFromCache(visibleCommit); + if (data == null) { + // no more continuous details in the cache break; } - boolean allFiltersMatch = !ContainerUtil.exists(detailsFilters, new Condition() { - @Override - public boolean value(VcsLogDetailsFilter filter) { - return !filter.matches(details); - } - }); - if (allFiltersMatch) { - result.add(details.getHash()); + if (matchesAllFilters(data, detailsFilters)) { + result.add(data.getHash()); } } return result; } + private static boolean matchesAllFilters(@NotNull final VcsCommitMetadata commit, @NotNull List detailsFilters) { + return !ContainerUtil.exists(detailsFilters, new Condition() { + @Override + public boolean value(VcsLogDetailsFilter filter) { + return !filter.matches(commit); + } + }); + } + @Nullable - private VcsFullCommitDetails getDetailsFromCache(final int commitIndex) { - final Ref ref = Ref.create(); + private VcsCommitMetadata getDetailsFromCache(final int commitIndex) { + final Hash hash = myLogDataHolder.getHash(commitIndex); + VcsCommitMetadata details = myLogDataHolder.getTopCommitDetails(hash); + if (details != null) { + return details; + } + final Ref ref = Ref.create(); UIUtil.invokeAndWaitIfNeeded(new Runnable() { @Override public void run() { - ref.set(myLogDataHolder.getCommitDetailsGetter().getCommitDataIfAvailable(myLogDataHolder.getHash(commitIndex))); + ref.set(myLogDataHolder.getCommitDetailsGetter().getCommitDataIfAvailable(hash)); } }); return ref.get(); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java index 69ed7b582b54..2354f4f6369e 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java @@ -23,6 +23,7 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; +import com.intellij.vcs.log.VcsCommitMetadata; import com.intellij.vcs.log.VcsFullCommitDetails; import com.intellij.vcs.log.VcsLogDetailsFilter; import com.intellij.vcs.log.VcsLogStructureFilter; @@ -68,18 +69,23 @@ public class VcsLogStructureFilterImpl implements VcsLogDetailsFilter, VcsLogStr } @Override - public boolean matches(@NotNull VcsFullCommitDetails details) { - for (Change change : details.getChanges()) { - ContentRevision before = change.getBeforeRevision(); - if (before != null && matches(before.getFile().getPath())) { - return true; - } - ContentRevision after = change.getAfterRevision(); - if (after != null && matches(after.getFile().getPath())) { - return true; + public boolean matches(@NotNull VcsCommitMetadata details) { + if ((details instanceof VcsFullCommitDetails)) { + for (Change change : ((VcsFullCommitDetails)details).getChanges()) { + ContentRevision before = change.getBeforeRevision(); + if (before != null && matches(before.getFile().getPath())) { + return true; + } + ContentRevision after = change.getAfterRevision(); + if (after != null && matches(after.getFile().getPath())) { + return true; + } } + return false; + } + else { + return false; } - return false; } private boolean matches(@NotNull final String path) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsChangesLazilyParsedDetails.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsChangesLazilyParsedDetails.java index 313c3248bd5f..a4932de63ee0 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsChangesLazilyParsedDetails.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsChangesLazilyParsedDetails.java @@ -31,9 +31,9 @@ import java.util.List; /** * Allows to postpone changes parsing, which might take long for a large amount of commits, - * because {@link Change} holds {@link FilePathImpl} which makes costly refreshes and type detections + * because {@link Change} holds {@link FilePathImpl} which makes costly refreshes and type detections. */ -public class VcsChangesLazilyParsedDetails extends VcsCommitDetailsExceptChanges implements VcsFullCommitDetails { +public class VcsChangesLazilyParsedDetails extends VcsCommitMetadataImpl implements VcsFullCommitDetails { private static final Logger LOG = Logger.getInstance(VcsChangesLazilyParsedDetails.class); diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsCommitDetailsExceptChanges.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsCommitMetadataImpl.java similarity index 64% rename from platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsCommitDetailsExceptChanges.java rename to platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsCommitMetadataImpl.java index cdd6b335f811..9d4c8db856d1 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsCommitDetailsExceptChanges.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsCommitMetadataImpl.java @@ -17,35 +17,30 @@ package com.intellij.vcs.log.impl; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcs.log.Hash; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsCommitMetadata; import com.intellij.vcs.log.VcsUser; import org.jetbrains.annotations.NotNull; import java.util.List; -/** - * Holds all information about commit, except {@link #getChanges() the changes} - * To allow to reuse common getters in implementations of different getChanges() laziness level. - */ -abstract class VcsCommitDetailsExceptChanges extends VcsShortCommitDetailsImpl implements VcsFullCommitDetails { +public class VcsCommitMetadataImpl extends VcsShortCommitDetailsImpl implements VcsCommitMetadata { @NotNull private final String myFullMessage; @NotNull private final VcsUser myCommitter; private final long myAuthorTime; - public VcsCommitDetailsExceptChanges(@NotNull Hash hash, @NotNull List parents, long timeStamp, @NotNull VirtualFile root, - @NotNull String subject, @NotNull VcsUser author, @NotNull String message, - @NotNull VcsUser committer, long authorTime) { + public VcsCommitMetadataImpl(@NotNull Hash hash, @NotNull List parents, long timeStamp, @NotNull VirtualFile root, + @NotNull String subject, @NotNull VcsUser author, @NotNull String message, + @NotNull VcsUser committer, long authorTime) { super(hash, parents, timeStamp, root, subject, author); myCommitter = committer; myAuthorTime = authorTime; myFullMessage = message; - } @Override @NotNull - public final String getFullMessage() { + public String getFullMessage() { return myFullMessage; } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsFullCommitDetailsImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsFullCommitDetailsImpl.java deleted file mode 100644 index 18e2d2177835..000000000000 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsFullCommitDetailsImpl.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.intellij.vcs.log.impl; - -import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ContentRevision; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.ContentRevisionFactory; -import com.intellij.vcs.log.Hash; -import com.intellij.vcs.log.VcsFullCommitDetails; -import com.intellij.vcs.log.VcsUser; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.List; - -public class VcsFullCommitDetailsImpl extends VcsCommitDetailsExceptChanges implements VcsFullCommitDetails { - - @NotNull private final Collection myChanges; - - public VcsFullCommitDetailsImpl(@NotNull Hash hash, @NotNull List parents, long time, @NotNull VirtualFile root, - @NotNull String subject, @NotNull VcsUser author, @NotNull String message, - @NotNull VcsUser committer, long authorTime, - @NotNull List changes, @NotNull final ContentRevisionFactory contentRevisionFactory) { - super(hash, parents, time, root, subject, author, message, committer, authorTime); - myChanges = ContainerUtil.map(changes, new Function() { - @Override - public LightChange fun(Change change) { - return LightChange.create(contentRevisionFactory, VcsFullCommitDetailsImpl.this, change); - } - }); - } - - @Override - @NotNull - public final Collection getChanges() { - return ContainerUtil.map(myChanges, new Function() { - @Override - public Change fun(LightChange change) { - return change.toChange(); - } - }); - } - - private static class LightChange { - - private ContentRevisionFactory myContentRevisionFactory; - private VcsFullCommitDetails myDetails; - private boolean myModification; - private VirtualFile myBeforeFile; - private VirtualFile myAfterFile; - private String myBeforePath; - private String myAfterPath; - - private static LightChange create(ContentRevisionFactory contentRevisionFactory, VcsFullCommitDetails details, Change change) { - LightChange lc = new LightChange(); - Change.Type type = change.getType(); - lc.myModification = type == Change.Type.MODIFICATION; - lc.myContentRevisionFactory = contentRevisionFactory; - - ContentRevision before = change.getBeforeRevision(); - if (before != null && !lc.myModification) { // don't store the same path twice (for modification store only after path) - FilePath filePath = before.getFile(); - if (filePath.getVirtualFile() == null) { - lc.myBeforePath = filePath.getIOFile().getPath(); - } - else { - lc.myBeforeFile = filePath.getVirtualFile(); - } - } - - ContentRevision after = change.getAfterRevision(); - if (after != null) { - FilePath filePath = after.getFile(); - if (filePath.getVirtualFile() == null) { - lc.myAfterPath = filePath.getIOFile().getPath(); - } - else { - lc.myAfterFile = filePath.getVirtualFile(); - } - } - - lc.myDetails = details; - return lc; - } - - Change toChange() { - List parents = myDetails.getParents(); - Hash parentHash = parents.isEmpty() ? null : parents.get(0); // no parents for the initial commit - - ContentRevision before = null; - if (parentHash != null) { - if (myBeforeFile != null) { - before = myContentRevisionFactory.createRevision(myBeforeFile, parentHash); - } - else if (myBeforePath != null) { - before = myContentRevisionFactory.createRevision(myDetails.getRoot(), myBeforePath, parentHash); - } - } - - ContentRevision after = null; - if (myAfterFile != null) { - after = myContentRevisionFactory.createRevision(myAfterFile, myDetails.getHash()); - if (myModification && parentHash != null) { // we didn't store myBeforeFile/Path to avoid duplicate path - before = myContentRevisionFactory.createRevision(myAfterFile, parentHash); - } - } - else if (myAfterPath != null) { - after = myContentRevisionFactory.createRevision(myDetails.getRoot(), myAfterPath, myDetails.getHash()); - if (myModification && parentHash != null) { - before = myContentRevisionFactory.createRevision(myDetails.getRoot(), myAfterPath, parentHash); - } - } - - return new Change(before, after); - } - - } -} 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 7be55fbfe93b..c17d4caea718 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 @@ -12,6 +12,7 @@ import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.changes.ui.ChangesViewContentManager; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ex.ToolWindowManagerListener; import com.intellij.openapi.wm.impl.ToolWindowImpl; @@ -31,6 +32,7 @@ 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.VcsLogUiImpl; +import com.intellij.vcs.log.ui.frame.VcsLogGraphTable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -80,6 +82,15 @@ public class VcsLogManager implements Disposable { myLogDataHolder = vcsLogDataHolder; myUi = logUI; mainPanel.init(logUI.getMainFrame().getMainComponent()); + final VcsLogGraphTable graphTable = logUI.getTable(); + if (graphTable.getRowCount() > 0) { + IdeFocusManager.getInstance(myProject).requestFocus(graphTable, true).doWhenProcessed(new Runnable() { + @Override + public void run() { + graphTable.setRowSelectionInterval(0, 0); + } + }); + } myLogRefresher = new PostponeableLogRefresher(myProject, vcsLogDataHolder); refreshLogOnVcsEvents(logProviders); } diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java index 79ce3a9565e7..ebd4e9a819ee 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogObjectsFactoryImpl.java @@ -1,6 +1,7 @@ package com.intellij.vcs.log.impl; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.NotNullFunction; @@ -8,6 +9,7 @@ import com.intellij.vcs.log.*; import com.intellij.vcs.log.data.VcsLogDataHolder; import org.jetbrains.annotations.NotNull; +import java.util.Collection; import java.util.List; /** @@ -52,15 +54,25 @@ public class VcsLogObjectsFactoryImpl implements VcsLogObjectsFactory { @NotNull @Override - public VcsFullCommitDetails createFullDetails(@NotNull Hash hash, @NotNull List parents, long time, @NotNull VirtualFile root, + public VcsCommitMetadata createCommitMetadata(@NotNull Hash hash, @NotNull List parents, long time, @NotNull VirtualFile root, @NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, @NotNull String message, @NotNull String committerName, - @NotNull String committerEmail, long authorTime, @NotNull List changes, - @NotNull ContentRevisionFactory contentRevisionFactory) { + @NotNull String committerEmail, long authorTime) { VcsUser author = createUser(authorName, authorEmail); VcsUser committer = createUser(committerName, committerEmail); - return new VcsFullCommitDetailsImpl(hash, parents, time, root, subject, author, message, committer, authorTime, - changes, contentRevisionFactory); + return new VcsCommitMetadataImpl(hash, parents, time, root, subject, author, message, committer, authorTime); + } + + @NotNull + @Override + public VcsFullCommitDetails createFullDetails(@NotNull Hash hash, @NotNull List parents, long time, VirtualFile root, + @NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, + @NotNull String message, @NotNull String committerName, @NotNull String committerEmail, + long authorTime, + @NotNull ThrowableComputable, ? extends Exception> changesGetter) { + VcsUser author = createUser(authorName, authorEmail); + VcsUser committer = createUser(committerName, committerEmail); + return new VcsChangesLazilyParsedDetails(hash, parents, time, root, subject, author, message, committer, authorTime, changesGetter); } @NotNull diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java index 192311e21512..f3dd27820b56 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUiImpl.java @@ -137,7 +137,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { @Override public void run() { final GraphAnswer answer = myDataPack.getGraphFacade().performAction(LinearBranchesExpansionAction.EXPAND); - UIUtil.invokeLaterIfNeeded(new Runnable() { + UIUtil.invokeAndWaitIfNeeded(new Runnable() { @Override public void run() { handleAnswer(answer); @@ -153,7 +153,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { @Override public void run() { final GraphAnswer answer = myDataPack.getGraphFacade().performAction(LinearBranchesExpansionAction.COLLAPSE); - UIUtil.invokeLaterIfNeeded(new Runnable() { + UIUtil.invokeAndWaitIfNeeded(new Runnable() { @Override public void run() { handleAnswer(answer); @@ -297,7 +297,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable { public void run() { final TIntHashSet previouslySelected = getSelectedCommits(); final AbstractVcsLogTableModel newModel = myFilterer.applyFiltersAndUpdateUi(dataPack, getFilters()); - UIUtil.invokeLaterIfNeeded(new Runnable() { + UIUtil.invokeAndWaitIfNeeded(new Runnable() { @Override public void run() { myDataPack = dataPack; diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java index 07febd5bc34c..fe696abb48e4 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java @@ -21,7 +21,7 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsCommitMetadata; import com.intellij.vcs.log.VcsLogUserFilter; import com.intellij.vcs.log.VcsUser; import com.intellij.vcs.log.data.VcsLogDataHolder; @@ -117,7 +117,7 @@ class UserFilterPopupComponent extends MultipleValueFilterPopupComponent() { @Override public boolean value(String user) { diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java index fa7363c4cfb7..80a0989c2c7f 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java @@ -15,7 +15,7 @@ */ package com.intellij.vcs.log.ui.filter; -import com.intellij.vcs.log.VcsFullCommitDetails; +import com.intellij.vcs.log.VcsCommitMetadata; import com.intellij.vcs.log.VcsLogTextFilter; import com.intellij.vcs.log.VcsLogDetailsFilter; import org.jetbrains.annotations.NotNull; @@ -29,7 +29,7 @@ public class VcsLogTextFilterImpl implements VcsLogDetailsFilter, VcsLogTextFilt } @Override - public boolean matches(@NotNull VcsFullCommitDetails details) { + public boolean matches(@NotNull VcsCommitMetadata details) { return details.getFullMessage().toLowerCase().contains(myText.toLowerCase()); } diff --git a/plugins/IntelliLang/src/META-INF/plugin.xml b/plugins/IntelliLang/src/META-INF/plugin.xml index b62e139cc20e..a6c430f242cf 100644 --- a/plugins/IntelliLang/src/META-INF/plugin.xml +++ b/plugins/IntelliLang/src/META-INF/plugin.xml @@ -47,7 +47,7 @@ - + diff --git a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java index 8547848a0ae3..3a3cc6e2b49b 100644 --- a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java +++ b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java @@ -25,6 +25,8 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.ThrowableComputable; +import com.intellij.openapi.vcs.changes.Change; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; @@ -36,7 +38,6 @@ import git4idea.config.GitVcsSettings; import git4idea.history.browser.GitHeavyCommit; import git4idea.history.wholeTree.AbstractHash; import git4idea.history.wholeTree.GitCommitDetailsProvider; -import git4idea.log.GitContentRevisionFactory; import git4idea.repo.GitRepository; import icons.Git4ideaIcons; import org.jetbrains.annotations.NotNull; @@ -212,10 +213,16 @@ public class GitCherryPickAction extends DumbAwareAction { return factory.createHash(hashValue); } }); + final List changes = commit.getChanges(); return factory.createFullDetails( factory.createHash(commit.getHash().getValue()), parents, commit.getAuthorTime(), commit.getRoot(), commit.getSubject(), commit.getAuthor(), commit.getAuthorEmail(), commit.getDescription(), commit.getCommitter(), commit.getCommitterEmail(), - commit.getDate().getTime(), commit.getChanges(), GitContentRevisionFactory.getInstance(project) + commit.getDate().getTime(), new ThrowableComputable, Exception>() { + @Override + public Collection compute() throws Exception { + return changes; + } + } ); } }); diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index 6b68987a1111..a0af85fbd870 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -35,10 +35,7 @@ import com.intellij.openapi.vcs.history.VcsRevisionDescription; import com.intellij.openapi.vcs.history.VcsRevisionDescriptionImpl; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.AsynchConsumer; -import com.intellij.util.Consumer; -import com.intellij.util.Function; -import com.intellij.util.SmartList; +import com.intellij.util.*; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import com.intellij.vcs.log.*; @@ -615,12 +612,7 @@ public class GitHistoryUtils { @NotNull private static TimedVcsCommit convert(@NotNull GitLogRecord rec, @NotNull VcsLogObjectsFactory factory) { - List parents = ContainerUtil.map(rec.getParentsHashes(), new Function() { - @Override - public Hash fun(String s) { - return HashImpl.build(s); - } - }); + List parents = getParentHashes(factory, rec); return factory.createTimedCommit(HashImpl.build(rec.getHash()), parents, rec.getCommitTime()); } @@ -743,6 +735,26 @@ public class GitHistoryUtils { return rc; } + @NotNull + public static List loadMetadata(@NotNull Project project, @NotNull final VirtualFile root, + @NotNull String... parameters) throws VcsException { + + final VcsLogObjectsFactory factory = getObjectsFactoryWithDisposeCheck(project); + if (factory == null) { + return Collections.emptyList(); + } + return loadDetails(project, root, false, new NullableFunction() { + @Nullable + @Override + public VcsCommitMetadata fun(GitLogRecord record) { + return factory.createCommitMetadata(factory.createHash(record.getHash()), getParentHashes(factory, record), record.getCommitTime(), + root, record.getSubject(), record.getAuthorName(), record.getAuthorEmail(), + record.getFullMessage(), record.getCommitterName(), record.getCommitterEmail(), + record.getAuthorTimeStamp()); + } + }, parameters); + } + /** *

Get & parse git log detailed output with commits, their parents and their changes.

* @@ -756,27 +768,9 @@ public class GitHistoryUtils { if (factory == null) { return Collections.emptyList(); } - - GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG); - GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, - AUTHOR_EMAIL, COMMITTER_NAME, COMMITTER_EMAIL, PARENTS, SUBJECT, BODY, RAW_BODY); - h.setStdoutSuppressed(true); - h.addParameters(parameters); - h.addParameters("-M", "--name-status", parser.getPretty(), "--encoding=UTF-8"); - h.addParameters("--full-history", "--sparse"); - h.endOptions(); - - StopWatch sw = StopWatch.start("git log --all-details"); - String output = h.run(); - sw.report(); - - sw = StopWatch.start("parsing"); - List records = parser.parse(output); - sw.report(); - - sw = StopWatch.start("Creating GitCommit objects"); - List gitCommits = ContainerUtil.mapNotNull(records, new Function() { + return loadDetails(project, root, true, new NullableFunction() { @Override + @Nullable public GitCommit fun(GitLogRecord record) { try { return createCommit(project, root, record, factory); @@ -786,25 +780,59 @@ public class GitHistoryUtils { return null; } } - }); + }, parameters); + } + + @NotNull + public static List loadDetails(@NotNull final Project project, @NotNull final VirtualFile root, boolean withChanges, + @NotNull NullableFunction converter, String... parameters) + throws VcsException { + GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG); + GitLogParser.NameStatus status = withChanges ? GitLogParser.NameStatus.STATUS : GitLogParser.NameStatus.NONE; + GitLogParser parser = new GitLogParser(project, status, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, + AUTHOR_EMAIL, COMMITTER_NAME, COMMITTER_EMAIL, PARENTS, SUBJECT, BODY, RAW_BODY); + h.setStdoutSuppressed(true); + h.addParameters(parameters); + h.addParameters(parser.getPretty(), "--encoding=UTF-8"); + h.addParameters("--full-history", "--sparse"); + if (withChanges) { + h.addParameters("-M", "--name-status"); + } + h.endOptions(); + + StopWatch sw = StopWatch.start("loading details"); + String output = h.run(); sw.report(); - return gitCommits; + + sw = StopWatch.start("parsing"); + List records = parser.parse(output); + sw.report(); + + sw = StopWatch.start("Creating objects"); + List commits = ContainerUtil.mapNotNull(records, converter); + sw.report(); + return commits; } private static GitCommit createCommit(@NotNull Project project, @NotNull VirtualFile root, @NotNull GitLogRecord record, @NotNull VcsLogObjectsFactory factory) throws VcsException { - List parents = ContainerUtil.map(record.getParentsHashes(), new Function() { - @Override - public Hash fun(String hash) { - return HashImpl.build(hash); - } - }); + List parents = getParentHashes(factory, record); return new GitCommit(project, HashImpl.build(record.getHash()), parents, record.getCommitTime(), root, record.getSubject(), factory.createUser(record.getAuthorName(), record.getAuthorEmail()), record.getFullMessage(), factory.createUser(record.getCommitterName(), record.getCommitterEmail()), record.getAuthorTimeStamp(), record.getStatusInfos()); } + @NotNull + private static List getParentHashes(@NotNull final VcsLogObjectsFactory factory, @NotNull GitLogRecord record) { + return ContainerUtil.map(record.getParentsHashes(), new Function() { + @Override + public Hash fun(String hash) { + return factory.createHash(hash); + } + }); + } + /** *

Returns the history queried by {@code git log}} command with a possibility to asynchronously process each log record * returned by Git.

diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java index 5a679d11ac69..ce19cd971045 100644 --- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java +++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java @@ -66,8 +66,7 @@ public class GitLogProvider implements VcsLogProvider { @NotNull @Override - public List readFirstBlock(@NotNull VirtualFile root, - boolean ordered, int commitCount) throws VcsException { + public List readFirstBlock(@NotNull VirtualFile root, boolean ordered, int commitCount) throws VcsException { if (!isRepositoryReady(root)) { return Collections.emptyList(); } @@ -77,7 +76,7 @@ public class GitLogProvider implements VcsLogProvider { if (ordered) { params = ArrayUtil.append(params, "--date-order"); } - return GitHistoryUtils.history(myProject, root, params); + return GitHistoryUtils.loadMetadata(myProject, root, params); } @NotNull @@ -92,7 +91,8 @@ public class GitLogProvider implements VcsLogProvider { @NotNull @Override - public List readShortDetails(@NotNull VirtualFile root, @NotNull List hashes) throws VcsException { + public List readShortDetails(@NotNull VirtualFile root, + @NotNull List hashes) throws VcsException { return GitHistoryUtils.readMiniDetails(myProject, root, hashes); } @@ -286,5 +286,4 @@ public class GitLogProvider implements VcsLogProvider { } return true; } - } \ No newline at end of file diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java b/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java index 66e8bde2d350..80074fb64a28 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchWidget.java @@ -122,7 +122,7 @@ public class GitBranchWidget extends EditorBasedWidget implements StatusBarWidge } @Override - // have to effect since the click opens a list popup, and the consumer is not called for the MultipleTextValuesPresentation + // have no effect since the click opens a list popup, and the consumer is not called for the MultipleTextValuesPresentation public Consumer getClickConsumer() { return new Consumer() { public void consume(MouseEvent mouseEvent) { diff --git a/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java b/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java index 5e220695dc20..f11d614bd917 100644 --- a/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java +++ b/plugins/git4idea/test-stepdefs/git4idea/GitCherryPickStepdefs.java @@ -20,6 +20,7 @@ import com.google.common.collect.Collections2; import com.intellij.dvcs.test.MockVcsHelper; import com.intellij.dvcs.test.MockVirtualFile; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FilePathImpl; import com.intellij.openapi.vcs.changes.Change; @@ -39,7 +40,6 @@ import cucumber.annotation.en.Then; import cucumber.annotation.en.When; import git4idea.cherrypick.GitCherryPicker; import git4idea.config.GitVersionSpecialty; -import git4idea.log.GitContentRevisionFactory; import java.util.*; @@ -260,11 +260,17 @@ public class GitCherryPickStepdefs { } private static VcsFullCommitDetails mockCommit(String hash, String message) { - List changes = new ArrayList(); + final List changes = new ArrayList(); changes.add(new Change(null, new MockContentRevision(new FilePathImpl(new MockVirtualFile("name")), VcsRevisionNumber.NULL))); return ServiceManager.getService(myProject, VcsLogObjectsFactory.class).createFullDetails( HashImpl.build(hash), Collections.emptyList(), 0, NullVirtualFile.INSTANCE, message, "John Smith", "john@mail.com", message, - "John Smith", "john@mail.com", 0, changes, GitContentRevisionFactory.getInstance(myProject)); + "John Smith", "john@mail.com", 0, new ThrowableComputable, Exception>() { + @Override + public Collection compute() throws Exception { + return changes; + } + } + ); } } \ No newline at end of file diff --git a/plugins/git4idea/tests/git4idea/log/RefParserTest.java b/plugins/git4idea/tests/git4idea/log/RefParserTest.java index f00fd079a459..c8966e684d2d 100644 --- a/plugins/git4idea/tests/git4idea/log/RefParserTest.java +++ b/plugins/git4idea/tests/git4idea/log/RefParserTest.java @@ -1,5 +1,6 @@ package git4idea.log; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.impl.NullVirtualFile; @@ -9,6 +10,7 @@ import com.intellij.vcs.log.impl.VcsRefImpl; import org.jetbrains.annotations.NotNull; import org.junit.Test; +import java.util.Collection; import java.util.List; import static junit.framework.Assert.assertEquals; @@ -70,7 +72,7 @@ public class RefParserTest { runTest("787ec72f340d740433ba068d4d58a6e58f6226bf", ""); } - private class TestLogObjectsFactory implements VcsLogObjectsFactory { + private static class TestLogObjectsFactory implements VcsLogObjectsFactory { @NotNull @Override public Hash createHash(@NotNull String stringHash) { @@ -96,13 +98,22 @@ public class RefParserTest { throw new UnsupportedOperationException(); } + @NotNull + @Override + public VcsFullCommitDetails createCommitMetadata(@NotNull Hash hash, @NotNull List parents, long time, VirtualFile root, + @NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, + @NotNull String message, @NotNull String committerName, @NotNull String committerEmail, + long authorTime) { + throw new UnsupportedOperationException(); + } + @NotNull @Override public VcsFullCommitDetails createFullDetails(@NotNull Hash hash, @NotNull List parents, long time, VirtualFile root, @NotNull String subject, @NotNull String authorName, @NotNull String authorEmail, @NotNull String message, @NotNull String committerName, @NotNull String committerEmail, - long authorTime, @NotNull List changes, - @NotNull ContentRevisionFactory contentRevisionFactory) { + long authorTime, + @NotNull ThrowableComputable, ? extends Exception> changesGetter) { throw new UnsupportedOperationException(); } diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 68d8b51364b7..e31fc8ad575d 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -217,6 +217,9 @@ + + + { - public GrInplaceIntroducer(@NotNull GrVariable elementToRename, - @NotNull Editor editor, - @NotNull Project project, - @NotNull String title, - @NotNull List occurrences, - @Nullable PsiElement elementToIntroduce) { - super(elementToRename, editor, project, title, PsiElement.EMPTY_ARRAY, elementToIntroduce); - setOccurrenceMarkers(occurrences); - } - - @Nullable - @Override - protected PsiElement getNameIdentifier() { - return getVariable().getNameIdentifierGroovy(); - } - - @Nullable - @Override - protected GrVariable getVariable() { - return (GrVariable)super.getVariable(); - } - - public abstract LinkedHashSet suggestNames(GrIntroduceContext context); -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java index e78cc0800d24..8eb7e29e5fe2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java @@ -738,7 +738,7 @@ public abstract class GrIntroduceHandlerBase T insertStatement(T declaration, + GrStatement anchor, + GrStatementOwner block, + boolean replaceAnchor) { + if (replaceAnchor) { + return (T)anchor.replace(declaration); + } + else { + return (T)block.addStatementBefore(declaration, anchor); + } + } + @NotNull static GrStatement insertBraces(@NotNull GrStatement anchor) { GrBlockStatement blockStatement = GroovyPsiElementFactory.getInstance(anchor.getProject()).createBlockStatement(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java index 849d2caaa6f4..f9c37080ad8e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java @@ -124,14 +124,17 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase123 +----- +label: def preved = 123 \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/label2.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/label2.test new file mode 100644 index 000000000000..9b5accf37461 --- /dev/null +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/label2.test @@ -0,0 +1,7 @@ +l:123 + +print 123 +----- +l: def preved = 123 + +print preved \ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/label3.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/label3.test new file mode 100644 index 000000000000..1b95bec00f2f --- /dev/null +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/label3.test @@ -0,0 +1,11 @@ +print 123 + +l:123 + +print 123 +----- +def preved = 123 +print preved + + +print preved \ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java index d1f63a0987e3..d4de24851d7c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java @@ -59,7 +59,7 @@ public class HgLogProvider implements VcsLogProvider { @NotNull @Override - public List readFirstBlock(@NotNull VirtualFile root, + public List readFirstBlock(@NotNull VirtualFile root, boolean ordered, int commitCount) throws VcsException { return HgHistoryUtil.history(myProject, root, commitCount, ordered ? Collections.emptyList() : Arrays.asList("-r", "0:tip")); } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java index ba72f36f50c0..e99e2004aedf 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java @@ -17,6 +17,7 @@ package org.zmlx.hg4idea.util; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.VcsException; @@ -35,7 +36,6 @@ import org.zmlx.hg4idea.action.HgCommandResultNotifier; import org.zmlx.hg4idea.command.HgLogCommand; import org.zmlx.hg4idea.execution.HgCommandException; import org.zmlx.hg4idea.execution.HgCommandResult; -import org.zmlx.hg4idea.log.HgContentRevisionFactory; import org.zmlx.hg4idea.provider.HgCommittedChangeList; import java.io.File; @@ -177,7 +177,7 @@ public class HgHistoryUtil { @NotNull private static VcsFullCommitDetails createCommit(@NotNull Project project, @NotNull VirtualFile root, - @NotNull HgCommittedChangeList record) { + @NotNull final HgCommittedChangeList record) { final VcsLogObjectsFactory factory = ServiceManager.getService(project, VcsLogObjectsFactory.class); HgRevisionNumber revNumber = (HgRevisionNumber)record.getRevisionNumber(); @@ -188,11 +188,17 @@ public class HgHistoryUtil { return factory.createHash(parent.getChangeset()); } }); + final Collection changes = record.getChanges(); return factory.createFullDetails(factory.createHash(revNumber.getChangeset()), parents, record.getCommitDate().getTime(), root, revNumber.getSubject(), revNumber.getAuthor(), revNumber.getEmail(), revNumber.getCommitMessage(), record.getCommitterName(), - "", record.getCommitDate().getTime(), - ContainerUtil.newArrayList(record.getChanges()), HgContentRevisionFactory.getInstance(project)); + "", record.getCommitDate().getTime(), new ThrowableComputable, Exception>() { + @Override + public Collection compute() throws Exception { + return changes; + } + } + ); } @Nullable