mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git.labs.intellij.net:idea/community
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
+2
-2
@@ -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;
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+2
-1
@@ -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,
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.intellij.vcs.log;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Full details of a commit: all metadata (commit message, author, committer, etc.) but without changes.</p>
|
||||
* <p>These details will be shown in dedicated panels displayed near the log, and can be used for in-memory filtering.</p>
|
||||
* <p>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}</p>
|
||||
*/
|
||||
public interface VcsCommitMetadata extends VcsShortCommitDetails {
|
||||
|
||||
@NotNull
|
||||
String getFullMessage();
|
||||
|
||||
@NotNull
|
||||
VcsUser getCommitter();
|
||||
|
||||
long getAuthorTime();
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* <p>Full details of a commit: all metadata (commit message, author, committer, etc.) and the changes.</p>
|
||||
* <p>These details will be shown in dedicated panels displayed near the log.</p>
|
||||
* <p>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}</p>
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
* All metadata + changes.
|
||||
*/
|
||||
public interface VcsFullCommitDetails extends VcsShortCommitDetails {
|
||||
|
||||
@NotNull
|
||||
String getFullMessage();
|
||||
public interface VcsFullCommitDetails extends VcsCommitMetadata {
|
||||
|
||||
@NotNull
|
||||
Collection<Change> getChanges();
|
||||
|
||||
@NotNull
|
||||
VcsUser getCommitter();
|
||||
|
||||
long getAuthorTime();
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Hash> parents, long timeStamp,
|
||||
VirtualFile root, @NotNull String subject, @NotNull String authorName, String authorEmail);
|
||||
|
||||
@NotNull
|
||||
VcsCommitMetadata createCommitMetadata(@NotNull Hash hash, @NotNull List<Hash> 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<Hash> 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<Change> 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<Collection<Change>, ? extends Exception> changesGetter);
|
||||
|
||||
@NotNull
|
||||
VcsUser createUser(@NotNull String name, @NotNull String email);
|
||||
|
||||
@@ -22,7 +22,7 @@ public interface VcsLogProvider {
|
||||
* Reads the given number of the most recent commits from the log.
|
||||
*/
|
||||
@NotNull
|
||||
List<? extends VcsFullCommitDetails> readFirstBlock(@NotNull VirtualFile root, boolean ordered, int commitCount) throws VcsException;
|
||||
List<? extends VcsCommitMetadata> readFirstBlock(@NotNull VirtualFile root, boolean ordered, int commitCount) throws VcsException;
|
||||
|
||||
/**
|
||||
* <p>Reads the whole history, but only hashes & parents.</p>
|
||||
|
||||
@@ -11,11 +11,12 @@ import java.util.List;
|
||||
* <p>These details will be displayed in the log table.</p>
|
||||
*
|
||||
* <p>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}
|
||||
* </p>
|
||||
*
|
||||
* @see VcsCommitMetadata
|
||||
* @see VcsFullCommitDetails
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public interface VcsShortCommitDetails {
|
||||
|
||||
|
||||
@@ -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<VcsFullCommitDetails> {
|
||||
|
||||
@@ -20,6 +20,12 @@ public class CommitDetailsGetter extends DataGetter<VcsFullCommitDetails> {
|
||||
super(dataHolder, logProviders, new VcsCommitCache<VcsFullCommitDetails>());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected VcsFullCommitDetails getFromAdditionalCache(@NotNull Hash hash) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<? extends VcsFullCommitDetails> readDetails(@NotNull VcsLogProvider logProvider, @NotNull VirtualFile root,
|
||||
|
||||
@@ -81,7 +81,7 @@ public abstract class DataGetter<T extends VcsShortCommitDetails> implements Dis
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <CommitId> 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<T extends VcsShortCommitDetails> implements Dis
|
||||
}
|
||||
return details;
|
||||
}
|
||||
return (T)myDataHolder.getTopCommitDetails(hash);
|
||||
return getFromAdditionalCache(hash);
|
||||
}
|
||||
|
||||
private <CommitId> 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<VirtualFile, Hash> commits = getCommitsAround(row, tableModel, UP_PRELOAD_COUNT, DOWN_PRELOAD_COUNT);
|
||||
for (Map.Entry<VirtualFile, Collection<Hash>> hashesByRoots : commits.entrySet()) {
|
||||
@@ -137,9 +143,8 @@ public abstract class DataGetter<T extends VcsShortCommitDetails> implements Dis
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static <CommitId> MultiMap<VirtualFile, Hash> getCommitsAround(int selectedRow,
|
||||
@NotNull AbstractVcsLogTableModel<?> model,
|
||||
int above, int below) {
|
||||
private static MultiMap<VirtualFile, Hash> getCommitsAround(int selectedRow, @NotNull AbstractVcsLogTableModel<?> model,
|
||||
int above, int below) {
|
||||
MultiMap<VirtualFile, Hash> commits = MultiMap.create();
|
||||
for (int row = Math.max(0, selectedRow - above); row < selectedRow + below && row < model.getRowCount(); row++) {
|
||||
Hash hash = model.getHashAtRow(row);
|
||||
|
||||
@@ -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.<Hash>emptyList(), -1, root, "Loading...", STUB_USER, "", STUB_USER, -1,
|
||||
Collections.<Change>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<Collection<Change>, Exception>() {
|
||||
@Override
|
||||
public Collection<Change> compute() throws Exception {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
});
|
||||
myLoadingTaskIndex = loadingTaskIndex;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<VcsShortCommitDetails> {
|
||||
|
||||
MiniDetailsGetter(@NotNull VcsLogDataHolder dataHolder, @NotNull Map<VirtualFile, VcsLogProvider> logProviders) {
|
||||
super(dataHolder, logProviders, new VcsCommitCache<VcsShortCommitDetails>());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected VcsShortCommitDetails getFromAdditionalCache(@NotNull Hash hash) {
|
||||
return myDataHolder.getTopCommitDetails(hash);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<? extends VcsShortCommitDetails> readDetails(@NotNull VcsLogProvider logProvider, @NotNull VirtualFile root,
|
||||
|
||||
@@ -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<Hash, VcsFullCommitDetails> myTopCommitsDetailsCache = ContainerUtil.newConcurrentMap();
|
||||
@NotNull private final Map<Hash, VcsCommitMetadata> 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<? extends VcsFullCommitDetails> firstBlockDetails = logProvider.readFirstBlock(root, orderedForRepo, commitCountForRepo);
|
||||
List<? extends VcsCommitMetadata> firstBlockDetails = logProvider.readFirstBlock(root, orderedForRepo, commitCountForRepo);
|
||||
sw.report();
|
||||
sw = StopWatch.start("readAllRefs for" + root.getName());
|
||||
Collection<VcsRef> newRefs = logProvider.readAllRefs(root);
|
||||
@@ -503,8 +503,8 @@ public class VcsLogDataHolder implements Disposable, VcsLogDataProvider {
|
||||
return infoByRoot.entrySet();
|
||||
}
|
||||
|
||||
private void storeUsers(@NotNull List<? extends VcsFullCommitDetails> details) {
|
||||
for (VcsFullCommitDetails detail : details) {
|
||||
private void storeUsers(@NotNull List<? extends VcsCommitMetadata> 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<? extends VcsFullCommitDetails> firstBlockDetails) {
|
||||
private void storeTopCommitsDetailsInCache(List<? extends VcsCommitMetadata> 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<TimedVcsCommit> getCommitsFromDetails(List<? extends VcsFullCommitDetails> firstBlockDetails) {
|
||||
List<TimedVcsCommit> commits = ContainerUtil.map(firstBlockDetails, new Function<VcsFullCommitDetails, TimedVcsCommit>() {
|
||||
private List<TimedVcsCommit> getCommitsFromDetails(List<? extends VcsCommitMetadata> firstBlockDetails) {
|
||||
List<TimedVcsCommit> commits = ContainerUtil.map(firstBlockDetails, new Function<VcsCommitMetadata, TimedVcsCommit>() {
|
||||
@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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -49,7 +49,7 @@ public class VcsLogFilterer {
|
||||
|
||||
private AbstractVcsLogTableModel applyDetailsFilter(DataPack dataPack, List<VcsLogDetailsFilter> detailsFilters) {
|
||||
if (!detailsFilters.isEmpty()) {
|
||||
List<Hash> filteredCommits = filterByDetails(dataPack, detailsFilters);
|
||||
List<Hash> 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<Hash> filterByDetails(@NotNull DataPack dataPack, @NotNull List<VcsLogDetailsFilter> detailsFilters) {
|
||||
private List<Hash> filterInMemory(@NotNull DataPack dataPack, @NotNull List<VcsLogDetailsFilter> detailsFilters) {
|
||||
List<Hash> result = ContainerUtil.newArrayList();
|
||||
int topCommits = myLogDataHolder.getSettings().getRecentCommitsCount();
|
||||
List<Integer> 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<VcsLogDetailsFilter>() {
|
||||
@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<VcsLogDetailsFilter> detailsFilters) {
|
||||
return !ContainerUtil.exists(detailsFilters, new Condition<VcsLogDetailsFilter>() {
|
||||
@Override
|
||||
public boolean value(VcsLogDetailsFilter filter) {
|
||||
return !filter.matches(commit);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VcsFullCommitDetails getDetailsFromCache(final int commitIndex) {
|
||||
final Ref<VcsFullCommitDetails> 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<VcsCommitMetadata> 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();
|
||||
|
||||
+16
-10
@@ -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) {
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
|
||||
+6
-11
@@ -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<Hash> 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<Hash> 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;
|
||||
}
|
||||
|
||||
@@ -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<LightChange> myChanges;
|
||||
|
||||
public VcsFullCommitDetailsImpl(@NotNull Hash hash, @NotNull List<Hash> parents, long time, @NotNull VirtualFile root,
|
||||
@NotNull String subject, @NotNull VcsUser author, @NotNull String message,
|
||||
@NotNull VcsUser committer, long authorTime,
|
||||
@NotNull List<Change> changes, @NotNull final ContentRevisionFactory contentRevisionFactory) {
|
||||
super(hash, parents, time, root, subject, author, message, committer, authorTime);
|
||||
myChanges = ContainerUtil.map(changes, new Function<Change, LightChange>() {
|
||||
@Override
|
||||
public LightChange fun(Change change) {
|
||||
return LightChange.create(contentRevisionFactory, VcsFullCommitDetailsImpl.this, change);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public final Collection<Change> getChanges() {
|
||||
return ContainerUtil.map(myChanges, new Function<LightChange, Change>() {
|
||||
@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<Hash> 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<Hash> parents, long time, @NotNull VirtualFile root,
|
||||
public VcsCommitMetadata createCommitMetadata(@NotNull Hash hash, @NotNull List<Hash> 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<Change> 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<Hash> 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<Collection<Change>, ? 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
|
||||
|
||||
@@ -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;
|
||||
|
||||
+2
-2
@@ -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<VcsLogU
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(@NotNull final VcsFullCommitDetails commit) {
|
||||
public boolean matches(@NotNull final VcsCommitMetadata commit) {
|
||||
return ContainerUtil.exists(getUserNames(commit.getRoot()), new Condition<String>() {
|
||||
@Override
|
||||
public boolean value(String user) {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<highlightErrorFilter implementation="org.intellij.plugins.intelliLang.inject.FrankensteinErrorFilter"/>
|
||||
<daemon.highlightInfoFilter implementation="org.intellij.plugins.intelliLang.inject.FrankensteinErrorFilter"/>
|
||||
|
||||
<projectConfigurable displayName="Language Injections" instance="org.intellij.plugins.intelliLang.InjectionsSettingsUI" nonDefaultProject="true"/>
|
||||
<projectConfigurable displayName="Language Injections" dynamic="true" instance="org.intellij.plugins.intelliLang.InjectionsSettingsUI" nonDefaultProject="true"/>
|
||||
|
||||
<multiHostInjector implementation="org.intellij.plugins.intelliLang.inject.CommentLanguageInjector"/>
|
||||
<multiHostInjector implementation="org.intellij.plugins.intelliLang.inject.TemporaryPlacesInjector"/>
|
||||
|
||||
@@ -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<Change> 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<Collection<Change>, Exception>() {
|
||||
@Override
|
||||
public Collection<Change> compute() throws Exception {
|
||||
return changes;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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<Hash> parents = ContainerUtil.map(rec.getParentsHashes(), new Function<String, Hash>() {
|
||||
@Override
|
||||
public Hash fun(String s) {
|
||||
return HashImpl.build(s);
|
||||
}
|
||||
});
|
||||
List<Hash> 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<? extends VcsCommitMetadata> 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<GitLogRecord, VcsCommitMetadata>() {
|
||||
@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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Get & parse git log detailed output with commits, their parents and their changes.</p>
|
||||
*
|
||||
@@ -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<GitLogRecord> records = parser.parse(output);
|
||||
sw.report();
|
||||
|
||||
sw = StopWatch.start("Creating GitCommit objects");
|
||||
List<GitCommit> gitCommits = ContainerUtil.mapNotNull(records, new Function<GitLogRecord, GitCommit>() {
|
||||
return loadDetails(project, root, true, new NullableFunction<GitLogRecord, GitCommit>() {
|
||||
@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 <T> List<T> loadDetails(@NotNull final Project project, @NotNull final VirtualFile root, boolean withChanges,
|
||||
@NotNull NullableFunction<GitLogRecord, T> 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<GitLogRecord> records = parser.parse(output);
|
||||
sw.report();
|
||||
|
||||
sw = StopWatch.start("Creating objects");
|
||||
List<T> 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<Hash> parents = ContainerUtil.map(record.getParentsHashes(), new Function<String, Hash>() {
|
||||
@Override
|
||||
public Hash fun(String hash) {
|
||||
return HashImpl.build(hash);
|
||||
}
|
||||
});
|
||||
List<Hash> 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<Hash> getParentHashes(@NotNull final VcsLogObjectsFactory factory, @NotNull GitLogRecord record) {
|
||||
return ContainerUtil.map(record.getParentsHashes(), new Function<String, Hash>() {
|
||||
@Override
|
||||
public Hash fun(String hash) {
|
||||
return factory.createHash(hash);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns the history queried by {@code git log}} command with a possibility to asynchronously process each log record
|
||||
* returned by Git.</p>
|
||||
|
||||
@@ -66,8 +66,7 @@ public class GitLogProvider implements VcsLogProvider {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<? extends VcsFullCommitDetails> readFirstBlock(@NotNull VirtualFile root,
|
||||
boolean ordered, int commitCount) throws VcsException {
|
||||
public List<? extends VcsCommitMetadata> 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<? extends VcsShortCommitDetails> readShortDetails(@NotNull VirtualFile root, @NotNull List<String> hashes) throws VcsException {
|
||||
public List<? extends VcsShortCommitDetails> readShortDetails(@NotNull VirtualFile root,
|
||||
@NotNull List<String> hashes) throws VcsException {
|
||||
return GitHistoryUtils.readMiniDetails(myProject, root, hashes);
|
||||
}
|
||||
|
||||
@@ -286,5 +286,4 @@ public class GitLogProvider implements VcsLogProvider {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<MouseEvent> getClickConsumer() {
|
||||
return new Consumer<MouseEvent>() {
|
||||
public void consume(MouseEvent mouseEvent) {
|
||||
|
||||
@@ -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<Change> changes = new ArrayList<Change>();
|
||||
final List<Change> changes = new ArrayList<Change>();
|
||||
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.<Hash>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<Collection<Change>, Exception>() {
|
||||
@Override
|
||||
public Collection<Change> compute() throws Exception {
|
||||
return changes;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Hash> 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<Hash> 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<Change> changes,
|
||||
@NotNull ContentRevisionFactory contentRevisionFactory) {
|
||||
long authorTime,
|
||||
@NotNull ThrowableComputable<Collection<Change>, ? extends Exception> changesGetter) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +217,9 @@
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<navbar implementation="org.jetbrains.plugins.groovy.navbar.GrNavBarModelExtension" order="after defaultNavbar"/>
|
||||
|
||||
<fileTypeDetector implementation="org.jetbrains.plugins.groovy.GroovyHashBangFileTypeDetector"/>
|
||||
|
||||
|
||||
<declarationRangeHandler key="org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod"
|
||||
implementationClass="org.jetbrains.plugins.groovy.codeInsight.hint.GrMethodDeclarationRangeHandler"/>
|
||||
<declarationRangeHandler key="org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition"
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -119,7 +119,7 @@ public class GrConcatenation2InjectorAdapter extends JavaConcatenationInjectorMa
|
||||
else if (right instanceof GrString) {
|
||||
processGString((GrString)right, operands);
|
||||
}
|
||||
else {
|
||||
else if (right != null) {
|
||||
operands.add(right);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 org.jetbrains.plugins.groovy;
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeRegistry;
|
||||
import com.intellij.openapi.util.io.ByteSequence;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Created by Max Medvedev on 17/03/14
|
||||
*/
|
||||
public class GroovyHashBangFileTypeDetector implements FileTypeRegistry.FileTypeDetector {
|
||||
@Nullable
|
||||
@Override
|
||||
public FileType detect(@NotNull VirtualFile file, @NotNull ByteSequence firstBytes, @Nullable CharSequence firstCharsIfText) {
|
||||
if (FileUtil.isHashBangLine(firstCharsIfText, "groovy")) {
|
||||
return GroovyFileType.GROOVY_FILE_TYPE;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+12
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -105,4 +105,15 @@ public class GrLabeledStatementImpl extends GroovyPsiElementImpl implements GrLa
|
||||
public PsiElement getNameIdentifier() {
|
||||
return getNameIdentifierGroovy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteChildInternal(@NotNull ASTNode child) {
|
||||
GrStatement statement = getStatement();
|
||||
if (statement != null && child == statement.getNode()) {
|
||||
delete();
|
||||
}
|
||||
else {
|
||||
super.deleteChildInternal(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1070,6 +1070,7 @@ public class PsiUtil {
|
||||
|
||||
final PsiElement parent = expr.getParent();
|
||||
if (parent instanceof GrControlFlowOwner || parent instanceof GrCaseSection) return true;
|
||||
if (parent instanceof GrLabeledStatement) return true;
|
||||
if (parent instanceof GrIfStatement &&
|
||||
(expr == ((GrIfStatement)parent).getThenBranch() || expr == ((GrIfStatement)parent).getElseBranch())) {
|
||||
return true;
|
||||
|
||||
+56
-49
@@ -162,57 +162,15 @@ public abstract class GrAbstractInplaceIntroducer<Settings extends GrIntroduceSe
|
||||
return var;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void moveOffsetAfter(boolean success) {
|
||||
super.moveOffsetAfter(success);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performIntroduce() {
|
||||
GrIntroduceContext context = new GrIntroduceContext() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor getEditor() {
|
||||
return myEditor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GrExpression getExpression() {
|
||||
return (GrExpression)getExpr();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GrVariable getVar() {
|
||||
return getLocalVariable();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StringPartInfo getStringPart() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement[] getOccurrences() {
|
||||
return restoreOccurrences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getScope() {
|
||||
return myScope;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getPlace() {
|
||||
GrExpression expression = getExpression();
|
||||
return expression != null ? expression : getLocalVariable();
|
||||
}
|
||||
};
|
||||
runRefactoring(context, getSettings(), true);
|
||||
runRefactoring(new IntroduceContextAdapter(), getSettings(), true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -278,4 +236,53 @@ public abstract class GrAbstractInplaceIntroducer<Settings extends GrIntroduceSe
|
||||
protected PsiType getSelectedType() {
|
||||
return myTypePointer != null ? myTypePointer.getType() : null;
|
||||
}
|
||||
|
||||
private class IntroduceContextAdapter implements GrIntroduceContext {
|
||||
@NotNull
|
||||
@Override
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Editor getEditor() {
|
||||
return myEditor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GrExpression getExpression() {
|
||||
return (GrExpression)getExpr();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public GrVariable getVar() {
|
||||
return getLocalVariable();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public StringPartInfo getStringPart() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement[] getOccurrences() {
|
||||
return restoreOccurrences();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getScope() {
|
||||
return myScope;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getPlace() {
|
||||
GrExpression expression = getExpression();
|
||||
return expression != null ? expression : getLocalVariable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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 org.jetbrains.plugins.groovy.refactoring.introduce;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.introduce.inplace.InplaceVariableIntroducer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Max Medvedev
|
||||
*/
|
||||
public abstract class GrInplaceIntroducer extends InplaceVariableIntroducer<PsiElement> {
|
||||
public GrInplaceIntroducer(@NotNull GrVariable elementToRename,
|
||||
@NotNull Editor editor,
|
||||
@NotNull Project project,
|
||||
@NotNull String title,
|
||||
@NotNull List<RangeMarker> 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<String> suggestNames(GrIntroduceContext context);
|
||||
}
|
||||
+1
-1
@@ -738,7 +738,7 @@ public abstract class GrIntroduceHandlerBase<Settings extends GrIntroduceSetting
|
||||
|
||||
@Nullable
|
||||
private static PsiElement findContainingStatement(@Nullable PsiElement candidate) {
|
||||
while (candidate != null && !PsiUtil.isExpressionStatement(candidate)) {
|
||||
while (candidate != null && (candidate.getParent() instanceof GrLabeledStatement || !(PsiUtil.isExpressionStatement(candidate)))) {
|
||||
candidate = candidate.getParent();
|
||||
if (candidate instanceof GrCaseLabel) candidate = candidate.getParent();
|
||||
}
|
||||
|
||||
+29
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -141,11 +141,17 @@ public abstract class GrIntroduceLocalVariableProcessor {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GrVariable insertVariableDefinition(@NotNull GrVariableDeclaration declaration, @NotNull GrStatement anchor, PsiElement expression) throws IncorrectOperationException {
|
||||
boolean deleteExpression = expression != null && PsiUtil.isExpressionStatement(expression) && !isSingleGStringInjectionExpr(expression);
|
||||
boolean anchorEqualsExpression = anchor == expression;
|
||||
private GrVariable insertVariableDefinition(@NotNull GrVariableDeclaration declaration,
|
||||
@NotNull GrStatement anchor,
|
||||
@Nullable PsiElement expression) throws IncorrectOperationException {
|
||||
GrLabeledStatement labeledStatement = expression != null && expression.getParent() instanceof GrLabeledStatement ? (GrLabeledStatement)expression.getParent() : null;
|
||||
|
||||
if (deleteExpression && !anchorEqualsExpression) {
|
||||
boolean expressionMustBeDeleted = expression != null && PsiUtil.isExpressionStatement(expression) && !isSingleGStringInjectionExpr(expression);
|
||||
boolean anchorEqualsExpression = anchor == expression || labeledStatement == anchor;
|
||||
|
||||
String usedLabel = labeledStatement != null ? labeledStatement.getName() : null;
|
||||
|
||||
if (expressionMustBeDeleted && !anchorEqualsExpression) {
|
||||
expression.delete();
|
||||
}
|
||||
|
||||
@@ -158,18 +164,20 @@ public abstract class GrIntroduceLocalVariableProcessor {
|
||||
|
||||
GrStatementOwner block = (GrStatementOwner)anchor.getParent();
|
||||
|
||||
if (deleteExpression && anchorEqualsExpression) {
|
||||
declaration = (GrVariableDeclaration)anchor.replace(declaration);
|
||||
if (usedLabel != null && expressionMustBeDeleted && anchorEqualsExpression) {
|
||||
GrLabeledStatement definitionWithLabel = (GrLabeledStatement)GroovyPsiElementFactory.getInstance(anchor.getProject()).createStatementFromText(usedLabel + ": foo()");
|
||||
GrLabeledStatement inserted = insertStatement(definitionWithLabel, anchor, block, true);
|
||||
declaration = inserted.getStatement().replaceWithStatement(declaration);
|
||||
}
|
||||
else {
|
||||
declaration = (GrVariableDeclaration)block.addStatementBefore(declaration, anchor);
|
||||
declaration = insertStatement(declaration, anchor, block, expressionMustBeDeleted && anchorEqualsExpression);
|
||||
}
|
||||
|
||||
final GrVariable variable = declaration.getVariables()[0];
|
||||
JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration);
|
||||
|
||||
|
||||
PsiElement markerPlace = deleteExpression ? variable :
|
||||
PsiElement markerPlace = expressionMustBeDeleted ? variable :
|
||||
isInsideControlStatement ? declaration.getParent()
|
||||
: expression;
|
||||
refreshPositionMarker(markerPlace);
|
||||
@@ -177,6 +185,18 @@ public abstract class GrIntroduceLocalVariableProcessor {
|
||||
return variable;
|
||||
}
|
||||
|
||||
private static <T extends GrStatement> 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();
|
||||
|
||||
+14
-5
@@ -124,14 +124,17 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
|
||||
// Generating variable declaration
|
||||
|
||||
GrVariable insertedVar = processExpression(context, settings);
|
||||
|
||||
if (context.getEditor() != null && getPositionMarker() != null) {
|
||||
context.getEditor().getCaretModel().moveToOffset(getPositionMarker().getEndOffset());
|
||||
context.getEditor().getSelectionModel().removeSelection();
|
||||
}
|
||||
moveOffsetToPositionMarker(context.getEditor());
|
||||
return insertedVar;
|
||||
}
|
||||
|
||||
private void moveOffsetToPositionMarker(Editor editor) {
|
||||
if (editor != null && getPositionMarker() != null) {
|
||||
editor.getSelectionModel().removeSelection();
|
||||
editor.getCaretModel().moveToOffset(getPositionMarker().getEndOffset());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GrInplaceVariableIntroducer getIntroducer(@NotNull GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
|
||||
|
||||
@@ -159,6 +162,12 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt
|
||||
return addVariable(context, settings);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performPostIntroduceTasks() {
|
||||
super.performPostIntroduceTasks();
|
||||
moveOffsetToPositionMarker(contextRef.get().getEditor());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -58,6 +58,9 @@ public class IntroduceVariableTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testLoop8() { doTest() }
|
||||
public void testInCase() { doTest() }
|
||||
public void testCaseLabel() { doTest() }
|
||||
public void testLabel1() { doTest() }
|
||||
public void testLabel2() { doTest() }
|
||||
public void testLabel3() { doTest() }
|
||||
|
||||
public void testDuplicatesInsideIf() { doTest() }
|
||||
public void testFromGString() { doTest() }
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
label: <begin>123<end>
|
||||
-----
|
||||
label: def preved = 123<caret>
|
||||
@@ -0,0 +1,7 @@
|
||||
l:<all>123<end>
|
||||
|
||||
print 123
|
||||
-----
|
||||
l: def preved = 123
|
||||
|
||||
print preved
|
||||
@@ -0,0 +1,11 @@
|
||||
print 123
|
||||
|
||||
l:<all>123<end>
|
||||
|
||||
print 123
|
||||
-----
|
||||
def preved = 123
|
||||
print preved
|
||||
|
||||
|
||||
print preved
|
||||
@@ -59,7 +59,7 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<? extends VcsFullCommitDetails> readFirstBlock(@NotNull VirtualFile root,
|
||||
public List<? extends VcsCommitMetadata> readFirstBlock(@NotNull VirtualFile root,
|
||||
boolean ordered, int commitCount) throws VcsException {
|
||||
return HgHistoryUtil.history(myProject, root, commitCount, ordered ? Collections.<String>emptyList() : Arrays.asList("-r", "0:tip"));
|
||||
}
|
||||
|
||||
@@ -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<Change> 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<Collection<Change>, Exception>() {
|
||||
@Override
|
||||
public Collection<Change> compute() throws Exception {
|
||||
return changes;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
Reference in New Issue
Block a user