[vcs-log] lambdify vcs-log-impl

This commit is contained in:
Julia Beliaeva
2016-05-27 00:17:11 +03:00
parent 0dd2a1be6a
commit 9f798a83aa
43 changed files with 309 additions and 770 deletions
@@ -65,12 +65,9 @@ abstract class AbstractDataGetter<T extends VcsShortCommitDetails> implements Di
myCache = cache;
Disposer.register(parentDisposable, this);
myLoader =
new SequentialLimitedLifoExecutor<TaskDescriptor>(this, MAX_LOADING_TASKS, new ThrowableConsumer<TaskDescriptor, VcsException>() {
@Override
public void consume(final TaskDescriptor task) throws VcsException {
preLoadCommitData(task.myCommits);
notifyLoaded();
}
new SequentialLimitedLifoExecutor<TaskDescriptor>(this, MAX_LOADING_TASKS, task -> {
preLoadCommitData(task.myCommits);
notifyLoaded();
});
}
@@ -166,13 +163,10 @@ abstract class AbstractDataGetter<T extends VcsShortCommitDetails> implements Di
}
private void sortCommitsByRow(@NotNull List<T> result, @NotNull final TIntIntHashMap rowsForCommits) {
ContainerUtil.sort(result, new Comparator<T>() {
@Override
public int compare(T details1, T details2) {
int row1 = rowsForCommits.get(myHashMap.getCommitIndex(details1.getId(), details1.getRoot()));
int row2 = rowsForCommits.get(myHashMap.getCommitIndex(details2.getId(), details2.getRoot()));
return Comparing.compare(row1, row2);
}
ContainerUtil.sort(result, (details1, details2) -> {
int row1 = rowsForCommits.get(myHashMap.getCommitIndex(details1.getId(), details1.getRoot()));
int row2 = rowsForCommits.get(myHashMap.getCommitIndex(details2.getId(), details2.getRoot()));
return Comparing.compare(row1, row2);
});
}
@@ -221,13 +215,7 @@ abstract class AbstractDataGetter<T extends VcsShortCommitDetails> implements Di
// fill the cache with temporary "Loading" values to avoid producing queries for each commit that has not been cached yet,
// even if it will be loaded within a previous query
if (!myCache.isKeyCached(commitId)) {
myCache.put(commitId, (T)new LoadingDetails(new Computable<CommitId>() {
@Override
public CommitId compute() {
return myHashMap.getCommitId(commitId);
}
}, taskNumber));
myCache.put(commitId, (T)new LoadingDetails(() -> myHashMap.getCommitId(commitId), taskNumber));
}
}
@@ -245,15 +233,12 @@ abstract class AbstractDataGetter<T extends VcsShortCommitDetails> implements Di
private Set<T> preLoadCommitData(@NotNull TIntHashSet commits) throws VcsException {
Set<T> result = ContainerUtil.newHashSet();
final MultiMap<VirtualFile, String> rootsAndHashes = MultiMap.create();
commits.forEach(new TIntProcedure() {
@Override
public boolean execute(int commit) {
CommitId commitId = myHashMap.getCommitId(commit);
if (commitId != null) {
rootsAndHashes.putValue(commitId.getRoot(), commitId.getHash().asString());
}
return true;
commits.forEach(commit -> {
CommitId commitId = myHashMap.getCommitId(commit);
if (commitId != null) {
rootsAndHashes.putValue(commitId.getRoot(), commitId.getHash().asString());
}
return true;
});
for (Map.Entry<VirtualFile, Collection<String>> entry : rootsAndHashes.entrySet()) {
@@ -53,31 +53,22 @@ public class ContainingBranchesGetter {
ContainingBranchesGetter(@NotNull VcsLogData logData, @NotNull Disposable parentDisposable) {
myLogData = logData;
myTaskExecutor = new SequentialLimitedLifoExecutor<Task>(parentDisposable, 10, new ThrowableConsumer<Task, Throwable>() {
@Override
public void consume(final Task task) throws Throwable {
final List<String> branches = task.getContainingBranches(myLogData);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
// if cache is cleared (because of log refresh) during this task execution,
// this will put obsolete value into the old instance we don't care anymore
task.cache.put(new CommitId(task.hash, task.root), branches);
notifyListeners();
}
});
}
myTaskExecutor = new SequentialLimitedLifoExecutor<Task>(parentDisposable, 10, task -> {
final List<String> branches = task.getContainingBranches(myLogData);
ApplicationManager.getApplication().invokeLater(() -> {
// if cache is cleared (because of log refresh) during this task execution,
// this will put obsolete value into the old instance we don't care anymore
task.cache.put(new CommitId(task.hash, task.root), branches);
notifyListeners();
});
});
myLogData.addDataPackChangeListener(new DataPackChangeListener() {
@Override
public void onDataPackChange(@NotNull DataPack dataPack) {
Collection<VcsRef> currentBranches = dataPack.getRefsModel().getBranches();
int checksum = currentBranches.hashCode();
if (myCurrentBranchesChecksum != 0 && myCurrentBranchesChecksum != checksum) { // clear cache if branches set changed after refresh
clearCache();
}
myCurrentBranchesChecksum = checksum;
myLogData.addDataPackChangeListener(dataPack -> {
Collection<VcsRef> currentBranches = dataPack.getRefsModel().getBranches();
int checksum = currentBranches.hashCode();
if (myCurrentBranchesChecksum != 0 && myCurrentBranchesChecksum != checksum) { // clear cache if branches set changed after refresh
clearCache();
}
myCurrentBranchesChecksum = checksum;
});
}
@@ -90,12 +81,7 @@ public class ContainingBranchesGetter {
c.dispose();
}
// re-request containing branches information for the commit user (possibly) currently stays on
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
notifyListeners();
}
});
ApplicationManager.getApplication().invokeLater(() -> notifyListeners());
}
/**
@@ -149,12 +135,8 @@ public class ContainingBranchesGetter {
PermanentGraph<Integer> graph = dataPack.getPermanentGraph();
VcsLogRefs refs = dataPack.getRefsModel();
VcsRef branchRef = ContainerUtil.find(refs.getBranches(), new Condition<VcsRef>() {
@Override
public boolean value(VcsRef vcsRef) {
return vcsRef.getRoot().equals(root) && vcsRef.getName().equals(branchName);
}
});
VcsRef branchRef = ContainerUtil.find(refs.getBranches(),
vcsRef -> vcsRef.getRoot().equals(root) && vcsRef.getName().equals(branchName));
if (branchRef == null) return Conditions.alwaysFalse();
ContainedInBranchCondition condition = myConditions.get(root);
if (condition == null || !condition.getBranch().equals(branchName)) {
@@ -71,14 +71,10 @@ public class DataPack extends DataPackBase {
@NotNull
public static Function<Integer, Hash> createHashGetter(@NotNull final VcsLogHashMap hashMap) {
return new Function<Integer, Hash>() {
@Nullable
@Override
public Hash fun(Integer commitIndex) {
CommitId commitId = hashMap.getCommitId(commitIndex);
if (commitId == null) return null;
return commitId.getHash();
}
return commitIndex -> {
CommitId commitId = hashMap.getCommitId(commitIndex);
if (commitId == null) return null;
return commitId.getHash();
};
}
@@ -58,12 +58,8 @@ public class FakeVisiblePackBuilder {
@NotNull VisibleGraphImpl<Integer> oldGraph,
@NotNull VcsLogFilterCollection filters) {
final PermanentGraphInfo<Integer> info = oldGraph.buildSimpleGraphInfo();
Set<Integer> heads = ContainerUtil.map2Set(info.getPermanentGraphLayout().getHeadNodeIndex(), new Function<Integer, Integer>() {
@Override
public Integer fun(Integer integer) {
return info.getPermanentCommitsInfo().getCommitId(integer);
}
});
Set<Integer> heads = ContainerUtil.map2Set(info.getPermanentGraphLayout().getHeadNodeIndex(),
integer -> info.getPermanentCommitsInfo().getCommitId(integer));
RefsModel newRefsModel = createRefsModel(oldPack.getRefsModel(), heads, oldGraph);
DataPackBase newPack = new DataPackBase(oldPack.getLogProviders(), newRefsModel, false);
@@ -85,18 +81,15 @@ public class FakeVisiblePackBuilder {
private RefsModel createRefsModel(@NotNull RefsModel refsModel,
@NotNull final Set<Integer> heads,
@NotNull final VisibleGraph<Integer> visibleGraph) {
Collection<VcsRef> branchesAndHeads = ContainerUtil.filter(refsModel.getAllRefs(), new Condition<VcsRef>() {
@Override
public boolean value(VcsRef ref) {
int commitIndex = myHashMap.getCommitIndex(ref.getCommitHash(), ref.getRoot());
if (ref.getType().isBranch() || heads.contains(commitIndex)) {
Integer row = visibleGraph.getVisibleRowIndex(commitIndex);
if (row != null && row >= 0) {
return true;
}
Collection<VcsRef> branchesAndHeads = ContainerUtil.filter(refsModel.getAllRefs(), ref -> {
int commitIndex = myHashMap.getCommitIndex(ref.getCommitHash(), ref.getRoot());
if (ref.getType().isBranch() || heads.contains(commitIndex)) {
Integer row = visibleGraph.getVisibleRowIndex(commitIndex);
if (row != null && row >= 0) {
return true;
}
return false;
}
return false;
});
return new RefsModel(VcsLogUtil.groupRefsByRoot(branchesAndHeads), heads, myHashMap);
}
@@ -48,15 +48,12 @@ public class InMemoryHashMap implements VcsLogHashMap {
@Override
public CommitId findCommitId(@NotNull final Condition<CommitId> condition) {
final CommitId[] result = new CommitId[]{null};
myEnumerator.forEachValue(new TObjectProcedure<CommitId>() {
@Override
public boolean execute(CommitId commitId) {
if (condition.value(commitId)) {
result[0] = commitId;
return false;
}
return true;
myEnumerator.forEachValue(commitId -> {
if (condition.value(commitId)) {
result[0] = commitId;
return false;
}
return true;
});
return result[0];
}
@@ -41,12 +41,10 @@ public class RefsModel implements VcsLogRefs {
myRefsToHashes = prepareRefsMap(allRefs);
myBranchesToIndices = prepareRefsToIndicesMap(myBranches, hashMap);
myRefsToHeadIndices = prepareRefsToIndicesMap(Iterables.filter(Iterables.concat(refsByRoot.values()), new Predicate<VcsRef>() {
@Override
public boolean apply(VcsRef vcsRef) {
return heads.contains(hashMap.getCommitIndex(vcsRef.getCommitHash(), vcsRef.getRoot()));
}
}), hashMap);
myRefsToHeadIndices = prepareRefsToIndicesMap(Iterables.filter(Iterables.concat(refsByRoot.values()),
vcsRef -> heads.contains(
hashMap.getCommitIndex(vcsRef.getCommitHash(), vcsRef.getRoot()))),
hashMap);
myRootsToHeadIndices = prepareRootsMap(heads, hashMap);
}
@@ -96,25 +96,10 @@ public class VcsLogBranchFilterImpl implements VcsLogBranchFilter {
List<String> result = new ArrayList<String>();
result.addAll(myBranches);
result.addAll(ContainerUtil.map(myPatterns, new Function<Pattern, String>() {
@Override
public String fun(Pattern pattern) {
return pattern.pattern();
}
}));
result.addAll(ContainerUtil.map(myPatterns, pattern -> pattern.pattern()));
result.addAll(ContainerUtil.map(myExcludedBranches, new Function<String, String>() {
@Override
public String fun(String branchName) {
return "-" + branchName;
}
}));
result.addAll(ContainerUtil.map(myExcludedPatterns, new Function<Pattern, String>() {
@Override
public String fun(Pattern pattern) {
return "-" + pattern.pattern();
}
}));
result.addAll(ContainerUtil.map(myExcludedBranches, branchName -> "-" + branchName));
result.addAll(ContainerUtil.map(myExcludedPatterns, pattern -> "-" + pattern.pattern()));
return result;
}
@@ -86,17 +86,10 @@ public class VcsLogData implements Disposable, VcsLogDataProvider {
myDetailsGetter = new CommitDetailsGetter(myHashMap, logProviders, this);
myRefresher =
new VcsLogRefresherImpl(myProject, myHashMap, myLogProviders, myUserRegistry, myTopCommitsDetailsCache, new Consumer<DataPack>() {
@Override
public void consume(DataPack dataPack) {
fireDataPackChangeEvent(dataPack);
}
}, new Consumer<Exception>() {
@Override
public void consume(Exception e) {
if (!(e instanceof ProcessCanceledException)) {
LOG.error(e);
}
new VcsLogRefresherImpl(myProject, myHashMap, myLogProviders, myUserRegistry, myTopCommitsDetailsCache,
dataPack -> fireDataPackChangeEvent(dataPack), e -> {
if (!(e instanceof ProcessCanceledException)) {
LOG.error(e);
}
}, RECENT_COMMITS_COUNT);
@@ -117,12 +110,9 @@ public class VcsLogData implements Disposable, VcsLogDataProvider {
}
private void fireDataPackChangeEvent(@NotNull final DataPack dataPack) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
for (DataPackChangeListener listener : myDataPackChangeListeners) {
listener.onDataPackChange(dataPack);
}
ApplicationManager.getApplication().invokeLater(() -> {
for (DataPackChangeListener listener : myDataPackChangeListeners) {
listener.onDataPackChange(dataPack);
}
});
}
@@ -165,15 +155,12 @@ public class VcsLogData implements Disposable, VcsLogDataProvider {
final StopWatch initSw = StopWatch.start("initialize");
myDataLoaderQueue.clear();
runInBackground(new ThrowableConsumer<ProgressIndicator, VcsException>() {
@Override
public void consume(ProgressIndicator indicator) throws VcsException {
resetState();
readCurrentUser();
DataPack dataPack = myRefresher.readFirstBlock();
fireDataPackChangeEvent(dataPack);
initSw.report();
}
runInBackground(indicator -> {
resetState();
readCurrentUser();
DataPack dataPack = myRefresher.readFirstBlock();
fireDataPackChangeEvent(dataPack);
initSw.report();
}, "Loading History...");
}
@@ -58,24 +58,18 @@ public class VcsLogFiltererImpl implements VcsLogFilterer {
myFilters = new VcsLogFilterCollectionImpl(null, null, null, null, null, null, null);
mySortType = initialSortType;
myTaskController = new SingleTaskController<Request, VisiblePack>(new Consumer<VisiblePack>() {
@Override
public void consume(@NotNull VisiblePack visiblePack) {
myVisiblePack = visiblePack;
for (VisiblePackChangeListener listener : myVisiblePackChangeListeners) {
listener.onVisiblePackChange(visiblePack);
}
myTaskController = new SingleTaskController<Request, VisiblePack>(visiblePack -> {
myVisiblePack = visiblePack;
for (VisiblePackChangeListener listener : myVisiblePackChangeListeners) {
listener.onVisiblePackChange(visiblePack);
}
}) {
@Override
protected void startNewBackgroundTask() {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
MyTask task = new MyTask(project, "Applying filters...");
ProgressManager.getInstance().runProcessWithProgressAsynchronously(task,
myLogData.getProgress().createProgressIndicator(task));
}
UIUtil.invokeLaterIfNeeded(() -> {
MyTask task = new MyTask(project, "Applying filters...");
ProgressManager.getInstance().runProcessWithProgressAsynchronously(task,
myLogData.getProgress().createProgressIndicator(task));
});
}
};
@@ -150,12 +144,9 @@ public class VcsLogFiltererImpl implements VcsLogFilterer {
final List<MoreCommitsRequest> requestsToRun = myRequestsToRun;
myRequestsToRun = ContainerUtil.newArrayList();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
for (MoreCommitsRequest request : requestsToRun) {
request.onLoaded.run();
}
ApplicationManager.getApplication().invokeLater(() -> {
for (MoreCommitsRequest request : requestsToRun) {
request.onLoaded.run();
}
});
}
@@ -205,12 +196,7 @@ public class VcsLogFiltererImpl implements VcsLogFilterer {
return new FakeVisiblePackBuilder(myLogData.getHashMap()).build(frozenVisiblePack);
}
Request nonValidateRequest = ContainerUtil.find(requests, new Condition<Request>() {
@Override
public boolean value(Request request) {
return !(request instanceof ValidateRequest);
}
});
Request nonValidateRequest = ContainerUtil.find(requests, request -> !(request instanceof ValidateRequest));
if (nonValidateRequest != null) {
// only doing something if there are some other requests
@@ -74,12 +74,9 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
myRecentCommitCount = recentCommitsCount;
myProgress = new VcsLogProgress();
mySingleTaskController = new SingleTaskController<RefreshRequest, DataPack>(new Consumer<DataPack>() {
@Override
public void consume(@NotNull DataPack dataPack) {
myDataPack = dataPack;
dataPackUpdateHandler.consume(dataPack);
}
mySingleTaskController = new SingleTaskController<RefreshRequest, DataPack>(dataPack -> {
myDataPack = dataPack;
dataPackUpdateHandler.consume(dataPack);
}) {
@Override
protected void startNewBackgroundTask() {
@@ -89,12 +86,9 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
}
protected void startNewBackgroundTask(@NotNull final Task.Backgroundable refreshTask) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
LOG.debug("Starting a background task...");
ProgressManager.getInstance().runProcessWithProgressAsynchronously(refreshTask, myProgress.createProgressIndicator(refreshTask));
}
UIUtil.invokeLaterIfNeeded(() -> {
LOG.debug("Starting a background task...");
ProgressManager.getInstance().runProcessWithProgressAsynchronously(refreshTask, myProgress.createProgressIndicator(refreshTask));
});
}
@@ -144,12 +138,7 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
@NotNull
private Map<VirtualFile, VcsLogProvider> getProvidersForRoots(@NotNull Set<VirtualFile> roots) {
return ContainerUtil.map2Map(roots,
new Function<VirtualFile, Pair<VirtualFile, VcsLogProvider>>() {
@Override
public Pair<VirtualFile, VcsLogProvider> fun(VirtualFile root) {
return Pair.create(root, myProviders.get(root));
}
});
root -> Pair.create(root, myProviders.get(root)));
}
@Override
@@ -184,13 +173,8 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
@NotNull
private GraphCommitImpl<Integer> compactCommit(@NotNull TimedVcsCommit commit, @NotNull final VirtualFile root) {
List<Integer> parents = ContainerUtil.map(commit.getParents(), new NotNullFunction<Hash, Integer>() {
@NotNull
@Override
public Integer fun(Hash hash) {
return myHashMap.getCommitIndex(hash, root);
}
});
List<Integer> parents = ContainerUtil.map(commit.getParents(),
(NotNullFunction<Hash, Integer>)hash -> myHashMap.getCommitIndex(hash, root));
return new GraphCommitImpl<Integer>(myHashMap.getCommitIndex(commit.getId(), root), parents, commit.getTimestamp());
}
@@ -322,12 +306,7 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
@NotNull Map<VirtualFile, Set<VcsRef>> previousRefs,
@NotNull Map<VirtualFile, Set<VcsRef>> newRefs) {
StopWatch sw = StopWatch.start("joining new commits");
Function<VcsRef, Integer> ref2Int = new Function<VcsRef, Integer>() {
@Override
public Integer fun(@NotNull VcsRef ref) {
return myHashMap.getCommitIndex(ref.getCommitHash(), ref.getRoot());
}
};
Function<VcsRef, Integer> ref2Int = ref -> myHashMap.getCommitIndex(ref.getCommitHash(), ref.getRoot());
Collection<Integer> prevRefIndices = ContainerUtil.map(ContainerUtil.concat(previousRefs.values()), ref2Int);
Collection<Integer> newRefIndices = ContainerUtil.map(ContainerUtil.concat(newRefs.values()), ref2Int);
try {
@@ -366,12 +345,7 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
@Override
void each(@NotNull final VirtualFile root, @NotNull VcsLogProvider provider) throws VcsException {
final List<GraphCommit<Integer>> graphCommits = ContainerUtil.newArrayList();
VcsLogProvider.LogData data = provider.readAllHashes(root, new Consumer<TimedVcsCommit>() {
@Override
public void consume(@NotNull TimedVcsCommit commit) {
graphCommits.add(compactCommit(commit, root));
}
});
VcsLogProvider.LogData data = provider.readAllHashes(root, commit -> graphCommits.add(compactCommit(commit, root)));
logInfo.put(root, graphCommits);
logInfo.put(root, data.getRefs());
myUserRegistry.addUsers(data.getUsers());
@@ -427,12 +401,8 @@ public class VcsLogRefresherImpl implements VcsLogRefresher {
@NotNull
Map<VirtualFile, VcsLogProvider.Requirements> asMap(@NotNull Collection<VirtualFile> roots) {
return ContainerUtil.map2Map(roots, new Function<VirtualFile, Pair<VirtualFile, VcsLogProvider.Requirements>>() {
@Override
public Pair<VirtualFile, VcsLogProvider.Requirements> fun(VirtualFile root) {
return Pair.<VirtualFile, VcsLogProvider.Requirements>create(root, CommitCountRequirements.this);
}
});
return ContainerUtil
.map2Map(roots, root -> Pair.<VirtualFile, VcsLogProvider.Requirements>create(root, CommitCountRequirements.this));
}
}
@@ -37,12 +37,7 @@ public class VcsLogStructureFilterImpl implements VcsLogDetailsFilter, VcsLogStr
@NotNull private final Collection<FilePath> myFiles;
public VcsLogStructureFilterImpl(@NotNull Set<VirtualFile> files) {
this(ContainerUtil.map(files, new Function<VirtualFile, FilePath>() {
@Override
public FilePath fun(VirtualFile file) {
return VcsUtil.getFilePath(file);
}
}));
this(ContainerUtil.map(files, file -> VcsUtil.getFilePath(file)));
}
public VcsLogStructureFilterImpl(@NotNull Collection<FilePath> files) {
@@ -96,12 +96,7 @@ public abstract class VcsLogUiPropertiesImpl implements PersistentStateComponent
@NotNull
private static List<List<String>> getRecentGroup(Deque<UserGroup> stateField) {
return ContainerUtil.map2List(stateField, new Function<UserGroup, List<String>>() {
@Override
public List<String> fun(UserGroup group) {
return group.users;
}
});
return ContainerUtil.map2List(stateField, group -> group.users);
}
@Override
@@ -45,12 +45,7 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry {
private static final File USER_CACHE_APP_DIR = new File(PathManager.getSystemPath(), "vcs-users");
private static final Logger LOG = Logger.getInstance(VcsUserRegistryImpl.class);
private static final int STORAGE_VERSION = 1;
private static final PersistentEnumeratorBase.DataFilter ACCEPT_ALL_DATA_FILTER = new PersistentEnumeratorBase.DataFilter() {
@Override
public boolean accept(int id) {
return true;
}
};
private static final PersistentEnumeratorBase.DataFilter ACCEPT_ALL_DATA_FILTER = id -> true;
@Nullable private final PersistentEnumerator<VcsUser> myPersistentEnumerator;
@NotNull private final Interner<VcsUser> myInterner;
@@ -64,12 +59,7 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry {
@Nullable
private PersistentEnumerator<VcsUser> initEnumerator(@NotNull final File mapFile) {
try {
return IOUtil.openCleanOrResetBroken(new ThrowableComputable<PersistentEnumerator<VcsUser>, IOException>() {
@Override
public PersistentEnumerator<VcsUser> compute() throws IOException {
return new PersistentEnumerator<VcsUser>(mapFile, new MyDescriptor(), Page.PAGE_SIZE);
}
}, mapFile);
return IOUtil.openCleanOrResetBroken(() -> new PersistentEnumerator<VcsUser>(mapFile, new MyDescriptor(), Page.PAGE_SIZE), mapFile);
}
catch (IOException e) {
LOG.warn(e);
@@ -111,12 +111,9 @@ class VisiblePackBuilder {
private VisiblePack applyHashFilter(@NotNull DataPack dataPack,
@NotNull Collection<String> hashes,
@NotNull PermanentGraph.SortType sortType) {
final Set<Integer> indices = ContainerUtil.map2SetNotNull(hashes, new Function<String, Integer>() {
@Override
public Integer fun(String partOfHash) {
CommitId commitId = myHashMap.findCommitId(new CommitIdByStringCondition(partOfHash));
return commitId != null ? myHashMap.getCommitIndex(commitId.getHash(), commitId.getRoot()) : null;
}
final Set<Integer> indices = ContainerUtil.map2SetNotNull(hashes, partOfHash -> {
CommitId commitId = myHashMap.findCommitId(new CommitIdByStringCondition(partOfHash));
return commitId != null ? myHashMap.getCommitIndex(commitId.getHash(), commitId.getRoot()) : null;
});
VisibleGraph<Integer> visibleGraph = dataPack.getPermanentGraph().createVisibleGraph(sortType, null, indices);
return new VisiblePack(dataPack, visibleGraph, false,
@@ -149,12 +146,9 @@ class VisiblePackBuilder {
}
private Set<Integer> getMatchingHeads(@NotNull VcsLogRefs refs, @NotNull final VcsLogBranchFilter filter) {
return new HashSet<Integer>(ContainerUtil.mapNotNull(refs.getBranches(), new Function<VcsRef, Integer>() {
@Override
public Integer fun(@NotNull VcsRef ref) {
boolean acceptRef = filter.matches(ref.getName());
return acceptRef ? myHashMap.getCommitIndex(ref.getCommitHash(), ref.getRoot()) : null;
}
return new HashSet<Integer>(ContainerUtil.mapNotNull(refs.getBranches(), ref -> {
boolean acceptRef = filter.matches(ref.getName());
return acceptRef ? myHashMap.getCommitIndex(ref.getCommitHash(), ref.getRoot()) : null;
}));
}
@@ -190,12 +184,7 @@ class VisiblePackBuilder {
@NotNull final PermanentGraph<Integer> permanentGraph,
@NotNull List<VcsLogDetailsFilter> detailsFilters,
@Nullable final Set<Integer> matchingHeads) {
boolean matchesAllDetails = ContainerUtil.and(detailsFilters, new Condition<VcsLogDetailsFilter>() {
@Override
public boolean value(VcsLogDetailsFilter filter) {
return filter.matches(commit);
}
});
boolean matchesAllDetails = ContainerUtil.and(detailsFilters, filter -> filter.matches(commit));
return matchesAllDetails && matchesAnyHead(permanentGraph, commit, matchingHeads);
}
@@ -216,12 +205,7 @@ class VisiblePackBuilder {
if (details != null) {
return details;
}
return UIUtil.invokeAndWaitIfNeeded(new Computable<VcsCommitMetadata>() {
@Override
public VcsCommitMetadata compute() {
return myCommitDetailsGetter.getCommitDataIfAvailable(commitIndex);
}
});
return UIUtil.invokeAndWaitIfNeeded((Computable<VcsCommitMetadata>)() -> myCommitDetailsGetter.getCommitDataIfAvailable(commitIndex));
}
@NotNull
@@ -248,12 +232,7 @@ class VisiblePackBuilder {
}
List<TimedVcsCommit> matchingCommits = entry.getValue().getCommitsMatchingFilter(root, rootSpecificCollection, maxCount);
logs.addAll(ContainerUtil.map(matchingCommits, new Function<TimedVcsCommit, CommitId>() {
@Override
public CommitId fun(TimedVcsCommit commit) {
return new CommitId(commit.getId(), root);
}
}));
logs.addAll(ContainerUtil.map(matchingCommits, commit -> new CommitId(commit.getId(), root)));
}
return logs;
@@ -274,11 +253,6 @@ class VisiblePackBuilder {
return null;
}
return ContainerUtil.map2Set(commits, new Function<CommitId, Integer>() {
@Override
public Integer fun(CommitId commitId) {
return myHashMap.getCommitIndex(commitId.getHash(), commitId.getRoot());
}
});
return ContainerUtil.map2Set(commits, commitId -> myHashMap.getCommitIndex(commitId.getHash(), commitId.getRoot()));
}
}
@@ -33,14 +33,11 @@ public class HeavyAwareExecutor implements Disposable {
}
public void execute(@NotNull Runnable command) {
SingleAlarm alarm = new SingleAlarm(new Runnable() {
@Override
public void run() {
if (!HeavyProcessLatch.INSTANCE.isRunning()) {
if (myIsExecuted.compareAndSet(false, true)) {
Disposer.dispose(HeavyAwareExecutor.this);
command.run();
}
SingleAlarm alarm = new SingleAlarm(() -> {
if (!HeavyProcessLatch.INSTANCE.isRunning()) {
if (myIsExecuted.compareAndSet(false, true)) {
Disposer.dispose(this);
command.run();
}
}
}, DELAY_MILLIS, Alarm.ThreadToUse.SWING_THREAD, this);
@@ -39,12 +39,9 @@ public class PostponableLogRefresher implements VcsLogRefresher {
public PostponableLogRefresher(@NotNull VcsLogData logData) {
myLogData = logData;
myLogData.addDataPackChangeListener(new DataPackChangeListener() {
@Override
public void onDataPackChange(@NotNull DataPack dataPack) {
for (VcsLogWindow window : myLogWindows) {
dataPackArrived(window.getFilterer(), window.isVisible());
}
myLogData.addDataPackChangeListener(dataPack -> {
for (VcsLogWindow window : myLogWindows) {
dataPackArrived(window.getFilterer(), window.isVisible());
}
});
}
@@ -53,12 +50,7 @@ public class PostponableLogRefresher implements VcsLogRefresher {
public Disposable addLogWindow(@NotNull VcsLogWindow window) {
myLogWindows.add(window);
filtererActivated(window.getFilterer(), true);
return new Disposable() {
@Override
public void dispose() {
myLogWindows.remove(window);
}
};
return () -> myLogWindows.remove(window);
}
@NotNull
@@ -102,15 +94,12 @@ public class PostponableLogRefresher implements VcsLogRefresher {
}
public void refresh(@NotNull final VirtualFile root) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (canRefreshNow()) {
myLogData.refresh(Collections.singleton(root));
}
else {
myRootsToRefresh.add(root);
}
ApplicationManager.getApplication().invokeLater(() -> {
if (canRefreshNow()) {
myLogData.refresh(Collections.singleton(root));
}
else {
myRootsToRefresh.add(root);
}
}, ModalityState.any());
}
@@ -61,12 +61,7 @@ public class TimedVcsCommitImpl implements TimedVcsCommit {
@Override
public String toString() {
return myHash.toShortString() + "|-" + StringUtil.join(ContainerUtil.map(myParents, new Function<Hash, String>() {
@Override
public String fun(Hash hash) {
return hash.toShortString();
}
}), ",") + ":" + myTime;
return myHash.toShortString() + "|-" + StringUtil.join(ContainerUtil.map(myParents, hash -> hash.toShortString()), ",") + ":" + myTime;
}
@Override
@@ -114,12 +114,8 @@ public class VcsLogContentProvider implements ChangesViewContentProvider {
return String.valueOf(tabbedContent.getTabs().size() + 1);
}
else {
List<Content> contents = ContainerUtil.filter(toolWindow.getContentManager().getContents(), new Condition<Content>() {
@Override
public boolean value(Content content) {
return TAB_NAME.equals(content.getUserData(Content.TAB_GROUP_NAME_KEY));
}
});
List<Content> contents = ContainerUtil.filter(toolWindow.getContentManager().getContents(),
content -> TAB_NAME.equals(content.getUserData(Content.TAB_GROUP_NAME_KEY)));
return String.valueOf(contents.size() + 1);
}
}
@@ -106,12 +106,7 @@ public class VcsLogImpl implements VcsLog {
@Override
public Future<Boolean> jumpToReference(final String reference) {
Collection<VcsRef> references = getAllReferences();
List<VcsRef> matchingRefs = ContainerUtil.findAll(references, new Condition<VcsRef>() {
@Override
public boolean value(VcsRef ref) {
return ref.getName().startsWith(reference);
}
});
List<VcsRef> matchingRefs = ContainerUtil.findAll(references, ref -> ref.getName().startsWith(reference));
if (matchingRefs.isEmpty()) {
return myUi.jumpToCommitByPartOfHash(reference);
}
@@ -206,16 +206,13 @@ public class VcsLogManager implements Disposable {
@Override
public void consume(@NotNull final Exception e) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (!myIsBroken) {
myIsBroken = true;
processErrorFirstTime(e);
}
else {
LOG.debug(e);
}
ApplicationManager.getApplication().invokeLater(() -> {
if (!myIsBroken) {
myIsBroken = true;
processErrorFirstTime(e);
}
else {
LOG.debug(e);
}
});
}
@@ -121,12 +121,8 @@ public class VcsLogTabsWatcher implements Disposable {
}
private void selectionChanged(String tabName) {
VcsLogWindow logWindow = ContainerUtil.find(myRefresher.getLogWindows(), new Condition<VcsLogWindow>() {
@Override
public boolean value(VcsLogWindow window) {
return window instanceof VcsLogTab && ((VcsLogTab)window).myTabName.equals(tabName);
}
});
VcsLogWindow logWindow = ContainerUtil.find(myRefresher.getLogWindows(),
window -> window instanceof VcsLogTab && ((VcsLogTab)window).myTabName.equals(tabName));
if (logWindow != null) {
myRefresher.filtererActivated(logWindow.getFilterer(), false);
}
@@ -39,35 +39,18 @@ public class VcsLogUtil {
@NotNull
public static Map<VirtualFile, Set<VcsRef>> groupRefsByRoot(@NotNull Collection<VcsRef> refs) {
return groupByRoot(refs, new Function<VcsRef, VirtualFile>() {
@NotNull
@Override
public VirtualFile fun(@NotNull VcsRef ref) {
return ref.getRoot();
}
});
return groupByRoot(refs, ref -> ref.getRoot());
}
@NotNull
public static <T extends VcsShortCommitDetails> Map<VirtualFile, Set<T>> groupByRoot(@NotNull Collection<T> commits) {
return groupByRoot(commits, new Function<T, VirtualFile>() {
@NotNull
@Override
public VirtualFile fun(@NotNull T commit) {
return commit.getRoot();
}
});
return groupByRoot(commits, commit -> commit.getRoot());
}
@NotNull
private static <T> Map<VirtualFile, Set<T>> groupByRoot(@NotNull Collection<T> items, @NotNull Function<T, VirtualFile> rootGetter) {
Map<VirtualFile, Set<T>> map =
new TreeMap<VirtualFile, Set<T>>(new Comparator<VirtualFile>() { // TODO some common VCS root sorting method
@Override
public int compare(@NotNull VirtualFile o1, @NotNull VirtualFile o2) {
return o1.getPresentableUrl().compareTo(o2.getPresentableUrl());
}
});
new TreeMap<VirtualFile, Set<T>>((o1, o2) -> o1.getPresentableUrl().compareTo(o2.getPresentableUrl()));
for (T item : items) {
VirtualFile root = rootGetter.fun(item);
Set<T> set = map.get(root);
@@ -103,12 +86,7 @@ public class VcsLogUtil {
private static Set<VirtualFile> collectRoots(@NotNull Collection<FilePath> files, @NotNull Set<VirtualFile> roots) {
Set<VirtualFile> selectedRoots = new HashSet<VirtualFile>();
List<VirtualFile> sortedRoots = ContainerUtil.sorted(roots, new Comparator<VirtualFile>() {
@Override
public int compare(VirtualFile root1, VirtualFile root2) {
return root1.getPath().compareTo(root2.getPath());
}
});
List<VirtualFile> sortedRoots = ContainerUtil.sorted(roots, (root1, root2) -> root1.getPath().compareTo(root2.getPath()));
for (FilePath filePath : files) {
VirtualFile virtualFile = filePath.getVirtualFile();
@@ -179,12 +157,9 @@ public class VcsLogUtil {
if (filterCollection.getStructureFilter() == null) return Collections.emptySet();
Collection<FilePath> files = filterCollection.getStructureFilter().getFiles();
return new HashSet<FilePath>(ContainerUtil.filter(files, new Condition<FilePath>() {
@Override
public boolean value(FilePath filePath) {
VirtualFile virtualFile = filePath.getVirtualFile();
return root.equals(virtualFile) || FileUtil.isAncestor(VfsUtilCore.virtualToIoFile(root), filePath.getIOFile(), false);
}
return new HashSet<FilePath>(ContainerUtil.filter(files, filePath -> {
VirtualFile virtualFile = filePath.getVirtualFile();
return root.equals(virtualFile) || FileUtil.isAncestor(VfsUtilCore.virtualToIoFile(root), filePath.getIOFile(), false);
}));
}
@@ -213,12 +188,7 @@ public class VcsLogUtil {
@NotNull
public static Collection<VcsRef> getVisibleBranches(@NotNull VcsLog log, @NotNull final Set<VirtualFile> visibleRoots) {
return ContainerUtil.filter(log.getAllReferences(), new Condition<VcsRef>() {
@Override
public boolean value(VcsRef ref) {
return visibleRoots.contains(ref.getRoot());
}
});
return ContainerUtil.filter(log.getAllReferences(), ref -> visibleRoots.contains(ref.getRoot()));
}
@NotNull
@@ -57,13 +57,7 @@ public class MyCommitsHighlighter implements VcsLogHighlighter {
// returns true if only one user commits to this repository
private boolean isSingleUser() {
NotNullFunction<VcsUser, String> nameToString = new NotNullFunction<VcsUser, String>() {
@NotNull
@Override
public String fun(VcsUser user) {
return VcsUserUtil.getNameInStandardForm(VcsUserUtil.getShortPresentation(user));
}
};
NotNullFunction<VcsUser, String> nameToString = user -> VcsUserUtil.getNameInStandardForm(VcsUserUtil.getShortPresentation(user));
Set<String> allUserNames = ContainerUtil.newHashSet(ContainerUtil.map(myLogData.getAllUsers(), nameToString));
Set<String> currentUserNames = ContainerUtil.newHashSet(ContainerUtil.map(myLogData.getCurrentUser().values(), nameToString));
return allUserNames.size() == currentUserNames.size() && currentUserNames.containsAll(allUserNames);
@@ -29,12 +29,7 @@ public class VcsLogColorManagerImpl implements VcsLogColorManager {
public VcsLogColorManagerImpl(@NotNull Collection<VirtualFile> roots) {
myRoots = new ArrayList<VirtualFile>(roots);
Collections.sort(myRoots, new Comparator<VirtualFile>() { // TODO add a common util method to sort roots
@Override
public int compare(VirtualFile o1, VirtualFile o2) {
return o1.getName().compareTo(o2.getName());
}
});
Collections.sort(myRoots, (o1, o2) -> o1.getName().compareTo(o2.getName()));
myRoots2Colors = ContainerUtil.newHashMap();
int i = 0;
for (VirtualFile root : myRoots) {
@@ -55,25 +50,15 @@ public class VcsLogColorManagerImpl implements VcsLogColorManager {
@NotNull
public static JBColor getBackgroundColor(@NotNull final Color baseRootColor) {
return new JBColor(new NotNullProducer<Color>() {
@NotNull
@Override
public Color produce() {
return ColorUtil.mix(baseRootColor, UIUtil.getTableBackground(), 0.75);
}
});
return new JBColor(() -> ColorUtil.mix(baseRootColor, UIUtil.getTableBackground(), 0.75));
}
@NotNull
public static JBColor getIndicatorColor(@NotNull final Color baseRootColor) {
if (Registry.is("vcs.log.square.labels")) return getBackgroundColor(baseRootColor);
return new JBColor(new NotNullProducer<Color>() {
@NotNull
@Override
public Color produce() {
if (UIUtil.isUnderDarcula()) return baseRootColor;
return ColorUtil.darker(ColorUtil.softer(baseRootColor), 2);
}
return new JBColor(() -> {
if (UIUtil.isUnderDarcula()) return baseRootColor;
return ColorUtil.darker(ColorUtil.softer(baseRootColor), 2);
});
}
@@ -60,12 +60,9 @@ public abstract class VcsLogPopupComponent extends JPanel {
add(Box.createHorizontalStrut(GAP_BEFORE_ARROW));
add(new JLabel(AllIcons.Ide.Statusbar_arrows));
installChangeListener(new Runnable() {
@Override
public void run() {
myValueLabel.revalidate();
myValueLabel.repaint();
}
installChangeListener(() -> {
myValueLabel.revalidate();
myValueLabel.repaint();
});
showPopupMenuOnClick();
showPopupMenuFromKeyboard();
@@ -68,19 +68,11 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable {
getTable().addHighlighter(factory.createHighlighter(logData, this));
}
myVisiblePackChangeListener = new VisiblePackChangeListener() {
@Override
public void onVisiblePackChange(@NotNull final VisiblePack visiblePack) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
if (!Disposer.isDisposed(VcsLogUiImpl.this)) {
setVisiblePack(visiblePack);
}
}
});
myVisiblePackChangeListener = visiblePack -> UIUtil.invokeLaterIfNeeded(() -> {
if (!Disposer.isDisposed(VcsLogUiImpl.this)) {
setVisiblePack(visiblePack);
}
};
});
myFilterer.addVisiblePackChangeListener(myVisiblePackChangeListener);
}
@@ -88,12 +80,7 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable {
// todo fix selection
final VcsLogGraphTable graphTable = myMainFrame.getGraphTable();
if (graphTable.getRowCount() > 0) {
IdeFocusManager.getInstance(myProject).requestFocus(graphTable, true).doWhenProcessed(new Runnable() {
@Override
public void run() {
graphTable.setRowSelectionInterval(0, 0);
}
});
IdeFocusManager.getInstance(myProject).requestFocus(graphTable, true).doWhenProcessed(() -> graphTable.setRowSelectionInterval(0, 0));
}
}
@@ -120,25 +107,19 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable {
}
private void performLongAction(@NotNull final GraphAction graphAction, @NotNull final String title) {
ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
final GraphAnswer<Integer> answer = myVisiblePack.getVisibleGraph().getActionController().performAction(graphAction);
final Runnable updater = answer.getGraphUpdater();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
assert updater != null : "Action:" +
title +
"\nController: " +
myVisiblePack.getVisibleGraph().getActionController() +
"\nAnswer:" +
answer;
updater.run();
getTable().handleAnswer(answer, true, null, null);
}
});
}
ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> {
final GraphAnswer<Integer> answer = myVisiblePack.getVisibleGraph().getActionController().performAction(graphAction);
final Runnable updater = answer.getGraphUpdater();
ApplicationManager.getApplication().invokeLater(() -> {
assert updater != null : "Action:" +
title +
"\nController: " +
myVisiblePack.getVisibleGraph().getActionController() +
"\nAnswer:" +
answer;
updater.run();
getTable().handleAnswer(answer, true, null, null);
});
}, title, false, null, getMainFrame().getMainComponent());
}
@@ -214,24 +195,14 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable {
@NotNull
public Future<Boolean> jumpToCommit(@NotNull Hash commitHash, @NotNull final VirtualFile root) {
SettableFuture<Boolean> future = SettableFuture.create();
jumpTo(commitHash, new PairFunction<GraphTableModel, Hash, Integer>() {
@Override
public Integer fun(GraphTableModel model, Hash hash) {
return model.getRowOfCommit(hash, root);
}
}, future);
jumpTo(commitHash, (model, hash) -> model.getRowOfCommit(hash, root), future);
return future;
}
@NotNull
public Future<Boolean> jumpToCommitByPartOfHash(@NotNull String commitHash) {
SettableFuture<Boolean> future = SettableFuture.create();
jumpTo(commitHash, new PairFunction<GraphTableModel, String, Integer>() {
@Override
public Integer fun(GraphTableModel model, String hash) {
return model.getRowOfCommitByPartOfHash(hash);
}
}, future);
jumpTo(commitHash, (model, hash) -> model.getRowOfCommitByPartOfHash(hash), future);
return future;
}
@@ -248,20 +219,10 @@ public class VcsLogUiImpl implements VcsLogUi, Disposable {
future.set(true);
}
else if (model.canRequestMore()) {
model.requestToLoadMore(new Runnable() {
@Override
public void run() {
jumpTo(commitId, rowGetter, future);
}
});
model.requestToLoadMore(() -> jumpTo(commitId, rowGetter, future));
}
else if (!myVisiblePack.isFull()) {
invokeOnChange(new Runnable() {
@Override
public void run() {
jumpTo(commitId, rowGetter, future);
}
});
invokeOnChange(() -> jumpTo(commitId, rowGetter, future));
}
else {
commitNotFound(commitId.toString());
@@ -42,17 +42,10 @@ public class GoToHashOrRefAction extends DumbAwareAction {
Set<VirtualFile> visibleRoots = VcsLogUtil.getVisibleRoots(logUi);
Collection<VcsRef> visibleBranches = VcsLogUtil.getVisibleBranches(log, visibleRoots);
GoToHashOrRefPopup popup = new GoToHashOrRefPopup(project, visibleBranches, visibleRoots, new Function<String, Future>() {
@Override
public Future fun(String text) {
return log.jumpToReference(text);
}
}, new Function<VcsRef, Future>() {
@Override
public Future fun(VcsRef vcsRef) {
return logUi.jumpToCommit(vcsRef.getCommitHash(), vcsRef.getRoot());
}
}, logUi.getColorManager(), new VcsGoToRefComparator(logUi.getDataPack().getLogProviders()));
GoToHashOrRefPopup popup = new GoToHashOrRefPopup(project, visibleBranches, visibleRoots, text -> log.jumpToReference(text),
vcsRef -> logUi.jumpToCommit(vcsRef.getCommitHash(), vcsRef.getRoot()),
logUi.getColorManager(),
new VcsGoToRefComparator(logUi.getDataPack().getLogProviders()));
popup.show(logUi.getTable());
}
@@ -83,23 +83,20 @@ public class GoToHashOrRefPopup {
: myOnSelectedRef.fun(mySelectedRef));
myFuture = future;
showProgress();
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
try {
future.get();
okPopup();
}
catch (CancellationException ex) {
cancelPopup();
}
catch (InterruptedException ex) {
cancelPopup();
}
catch (ExecutionException ex) {
LOG.error(ex);
cancelPopup();
}
ApplicationManager.getApplication().executeOnPooledThread(() -> {
try {
future.get();
okPopup();
}
catch (CancellationException ex) {
cancelPopup();
}
catch (InterruptedException ex) {
cancelPopup();
}
catch (ExecutionException ex) {
LOG.error(ex);
cancelPopup();
}
});
}
@@ -135,21 +132,11 @@ public class GoToHashOrRefPopup {
}
private void cancelPopup() {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myPopup.cancel();
}
});
ApplicationManager.getApplication().invokeLater(() -> myPopup.cancel());
}
private void okPopup() {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
myPopup.closeOk(null);
}
});
ApplicationManager.getApplication().invokeLater(() -> myPopup.closeOk(null));
}
public void show(@NotNull JComponent anchor) {
@@ -243,24 +230,18 @@ public class GoToHashOrRefPopup {
@Nullable
@Override
protected InsertHandler<LookupElement> createInsertHandler(@NotNull VcsRef item) {
return new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
mySelectedRef = (VcsRef)item.getObject();
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
// handleInsert is called in the middle of some other code that works with editor
// (see CodeCompletionHandlerBase.insertItem)
// for example, scrolls editor
// problem is that in onOk we make text field not editable
// by some reason this is done by disposing its editor and creating a new one
// so editor gets disposed here and CodeCompletionHandlerBase can not finish doing whatever it is doing with it
// I counter this by invoking onOk in invokeLater
myTextField.onOk();
}
});
}
return (context, item1) -> {
mySelectedRef = (VcsRef)item1.getObject();
ApplicationManager.getApplication().invokeLater(() -> {
// handleInsert is called in the middle of some other code that works with editor
// (see CodeCompletionHandlerBase.insertItem)
// for example, scrolls editor
// problem is that in onOk we make text field not editable
// by some reason this is done by disposing its editor and creating a new one
// so editor gets disposed here and CodeCompletionHandlerBase can not finish doing whatever it is doing with it
// I counter this by invoking onOk in invokeLater
myTextField.onOk();
});
};
}
}
@@ -42,12 +42,9 @@ public class IntelliSortChooserPopupAction extends DumbAwareAction {
final VcsLogUi logUI = e.getRequiredData(VcsLogDataKeys.VCS_LOG_UI);
ActionGroup settingsGroup =
new DefaultActionGroup(ContainerUtil.map(PermanentGraph.SortType.values(), new Function<PermanentGraph.SortType, AnAction>() {
@Override
public AnAction fun(PermanentGraph.SortType sortType) {
return new SelectIntelliSortTypeAction(logUI, sortType);
}
}));
new DefaultActionGroup(ContainerUtil.map(PermanentGraph.SortType.values(),
(Function<PermanentGraph.SortType, AnAction>)sortType -> new SelectIntelliSortTypeAction(
logUI, sortType)));
ListPopup popup = JBPopupFactory.getInstance()
@@ -66,12 +66,7 @@ public class BranchFilterPopupComponent extends MultipleValueFilterPopupComponen
@Override
protected VcsLogBranchFilter createFilter(@NotNull Collection<String> values) {
return VcsLogBranchFilterImpl
.fromTextPresentation(values, ContainerUtil.map2Set(myUi.getDataPack().getRefs().getBranches(), new Function<VcsRef, String>() {
@Override
public String fun(VcsRef vcsRef) {
return vcsRef.getName();
}
}));
.fromTextPresentation(values, ContainerUtil.map2Set(myUi.getDataPack().getRefs().getBranches(), vcsRef -> vcsRef.getName()));
}
@Override
@@ -118,12 +113,7 @@ public class BranchFilterPopupComponent extends MultipleValueFilterPopupComponen
@NotNull
@Override
protected List<String> getAllValues() {
return ContainerUtil.map(myFilterModel.getDataPack().getRefs().getBranches(), new Function<VcsRef, String>() {
@Override
public String fun(VcsRef ref) {
return ref.getName();
}
});
return ContainerUtil.map(myFilterModel.getDataPack().getRefs().getBranches(), ref -> ref.getName());
}
private class MyBranchPopupBuilder extends BranchPopupBuilder {
@@ -79,12 +79,7 @@ public abstract class BranchPopupBuilder {
if (recentItem.size() == 1) {
final String item = ContainerUtil.getFirstItem(recentItem);
if (filteredGroups.singletonGroups.contains(item) ||
ContainerUtil.find(filteredGroups.expandedGroups.values(), new Condition<TreeSet<String>>() {
@Override
public boolean value(TreeSet<String> strings) {
return strings.contains(item);
}
}) != null) {
ContainerUtil.find(filteredGroups.expandedGroups.values(), strings -> strings.contains(item)) != null) {
continue;
}
}
@@ -99,12 +99,9 @@ class MultilinePopupBuilder {
@NotNull
Collection<String> getSelectedValues() {
return ContainerUtil.mapNotNull(StringUtil.tokenize(myTextField.getText(), new String(SEPARATORS)), new Function<String, String>() {
@Override
public String fun(String value) {
String trimmed = value.trim();
return trimmed.isEmpty() ? null : trimmed;
}
return ContainerUtil.mapNotNull(StringUtil.tokenize(myTextField.getText(), new String(SEPARATORS)), value -> {
String trimmed = value.trim();
return trimmed.isEmpty() ? null : trimmed;
});
}
@@ -87,13 +87,8 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogFileFilte
final boolean shorten,
boolean full) {
return getText(files, category, shorten ? FILE_BY_NAME_COMPARATOR : FILE_BY_PATH_COMPARATOR,
new NotNullFunction<VirtualFile, String>() {
@NotNull
@Override
public String fun(VirtualFile file) {
return shorten ? file.getName() : StringUtil.shortenPathWithEllipsis(file.getPresentableUrl(), FILTER_LABEL_LENGTH);
}
}, full);
file -> shorten ? file.getName() : StringUtil.shortenPathWithEllipsis(file.getPresentableUrl(), FILTER_LABEL_LENGTH),
full);
}
private static String getTextFromFilePaths(@NotNull Collection<FilePath> files,
@@ -101,13 +96,8 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogFileFilte
final boolean shorten,
boolean full) {
return getText(files, category, shorten ? FILE_PATH_BY_NAME_COMPARATOR : FILE_PATH_BY_PATH_COMPARATOR,
new NotNullFunction<FilePath, String>() {
@NotNull
@Override
public String fun(FilePath file) {
return shorten ? file.getName() : StringUtil.shortenPathWithEllipsis(file.getPresentableUrl(), FILTER_LABEL_LENGTH);
}
}, full);
file -> shorten ? file.getName() : StringUtil.shortenPathWithEllipsis(file.getPresentableUrl(), FILTER_LABEL_LENGTH),
full);
}
private static <F> String getText(@NotNull Collection<F> files,
@@ -158,24 +148,12 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogFileFilte
private static String getTooltipTextForRoots(Collection<VirtualFile> files, final boolean shorten) {
return getTooltipTextForFiles(files, shorten ? FILE_BY_NAME_COMPARATOR : FILE_BY_PATH_COMPARATOR,
new NotNullFunction<VirtualFile, String>() {
@NotNull
@Override
public String fun(VirtualFile file) {
return shorten ? file.getName() : file.getPresentableUrl();
}
});
file -> shorten ? file.getName() : file.getPresentableUrl());
}
private static String getTooltipTextForFilePaths(Collection<FilePath> files, final boolean shorten) {
return getTooltipTextForFiles(files, shorten ? FILE_PATH_BY_NAME_COMPARATOR : FILE_PATH_BY_PATH_COMPARATOR,
new NotNullFunction<FilePath, String>() {
@NotNull
@Override
public String fun(FilePath file) {
return shorten ? file.getName() : file.getPresentableUrl();
}
});
file -> shorten ? file.getName() : file.getPresentableUrl());
}
private static <F> String getTooltipTextForFiles(@NotNull Collection<F> files,
@@ -394,12 +372,9 @@ class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogFileFilte
files = Collections.emptySet();
}
else {
files = ContainerUtil.mapNotNull(filter.getStructureFilter().getFiles(), new Function<FilePath, VirtualFile>() {
@Override
public VirtualFile fun(FilePath filePath) {
// for now, ignoring non-existing paths
return filePath.getVirtualFile();
}
files = ContainerUtil.mapNotNull(filter.getStructureFilter().getFiles(), filePath -> {
// for now, ignoring non-existing paths
return filePath.getVirtualFile();
});
}
@@ -94,14 +94,11 @@ class UserFilterPopupComponent extends MultipleValueFilterPopupComponent<VcsLogU
@NotNull
@Override
protected List<String> getAllValues() {
return ContainerUtil.map(myLogData.getAllUsers(), new Function<VcsUser, String>() {
@Override
public String fun(VcsUser user) {
String shortPresentation = VcsUserUtil.getShortPresentation(user);
Couple<String> firstAndLastName = VcsUserUtil.getFirstAndLastName(shortPresentation);
if (firstAndLastName == null) return shortPresentation;
return VcsUserUtil.capitalizeName(firstAndLastName.first) + " " + VcsUserUtil.capitalizeName(firstAndLastName.second);
}
return ContainerUtil.map(myLogData.getAllUsers(), user -> {
String shortPresentation = VcsUserUtil.getShortPresentation(user);
Couple<String> firstAndLastName = VcsUserUtil.getFirstAndLastName(shortPresentation);
if (firstAndLastName == null) return shortPresentation;
return VcsUserUtil.capitalizeName(firstAndLastName.first) + " " + VcsUserUtil.capitalizeName(firstAndLastName.second);
});
}
@@ -84,13 +84,7 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
myUiProperties = uiProperties;
myDataPack = initialDataPack;
NotNullComputable<VcsLogDataPack> dataPackGetter = new NotNullComputable<VcsLogDataPack>() {
@NotNull
@Override
public VcsLogDataPack compute() {
return myDataPack;
}
};
NotNullComputable<VcsLogDataPack> dataPackGetter = () -> myDataPack;
myBranchFilterModel = new BranchFilterModel(dataPackGetter);
myUserFilterModel = new FilterModel<VcsLogUserFilter>(dataPackGetter);
myDateFilterModel = new FilterModel<VcsLogDateFilter>(dataPackGetter);
@@ -103,13 +97,10 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
private void updateUiOnFilterChange() {
FilterModel[] models = {myBranchFilterModel, myUserFilterModel, myDateFilterModel, myStructureFilterModel, myTextFilterModel};
for (FilterModel<?> model : models) {
model.addSetFilterListener(new Runnable() {
@Override
public void run() {
myUi.applyFiltersAndUpdateUi();
myBranchFilterModel
.onStructureFilterChanged(new HashSet<VirtualFile>(myLogData.getRoots()), myStructureFilterModel.getFilter());
}
model.addSetFilterListener(() -> {
myUi.applyFiltersAndUpdateUi();
myBranchFilterModel
.onStructureFilterChanged(new HashSet<VirtualFile>(myLogData.getRoots()), myStructureFilterModel.getFilter());
});
}
}
@@ -127,12 +118,9 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
}
};
textFilter.setText(myTextFilterModel.getText());
textFilter.getTextEditor().addActionListener(new ActionListener() {
@Override
public void actionPerformed(@NotNull ActionEvent e) {
myTextFilterModel.setFilter(new VcsLogTextFilterImpl(textFilter.getText()));
textFilter.addCurrentTextToHistory();
}
textFilter.getTextEditor().addActionListener(e -> {
myTextFilterModel.setFilter(new VcsLogTextFilterImpl(textFilter.getText()));
textFilter.addCurrentTextToHistory();
});
textFilter.addDocumentListener(new DocumentAdapter() {
@Override
@@ -158,30 +146,11 @@ public class VcsLogClassicFilterUi implements VcsLogFilterUi {
@NotNull
public ActionGroup createActionGroup() {
DefaultActionGroup actionGroup = new DefaultActionGroup();
actionGroup.add(new FilterActionComponent(new Computable<JComponent>() {
@Override
public JComponent compute() {
return new BranchFilterPopupComponent(myUi, myUiProperties, myBranchFilterModel).initUi();
}
}));
actionGroup.add(new FilterActionComponent(new Computable<JComponent>() {
@Override
public JComponent compute() {
return new UserFilterPopupComponent(myUiProperties, myLogData, myUserFilterModel).initUi();
}
}));
actionGroup.add(new FilterActionComponent(new Computable<JComponent>() {
@Override
public JComponent compute() {
return new DateFilterPopupComponent(myDateFilterModel).initUi();
}
}));
actionGroup.add(new FilterActionComponent(new Computable<JComponent>() {
@Override
public JComponent compute() {
return new StructureFilterPopupComponent(myStructureFilterModel, myUi.getColorManager()).initUi();
}
}));
actionGroup.add(new FilterActionComponent(() -> new BranchFilterPopupComponent(myUi, myUiProperties, myBranchFilterModel).initUi()));
actionGroup.add(new FilterActionComponent(() -> new UserFilterPopupComponent(myUiProperties, myLogData, myUserFilterModel).initUi()));
actionGroup.add(new FilterActionComponent(() -> new DateFilterPopupComponent(myDateFilterModel).initUi()));
actionGroup.add(new FilterActionComponent(
() -> new StructureFilterPopupComponent(myStructureFilterModel, myUi.getColorManager()).initUi()));
return actionGroup;
}
@@ -52,12 +52,7 @@ public class VcsLogUserFilterImpl implements VcsLogUserFilter {
for (String user : myUsers) {
Set<VcsUser> users = getUsers(root, user);
if (!users.isEmpty()) {
result.addAll(ContainerUtil.map(users, new Function<VcsUser, String>() {
@Override
public String fun(VcsUser user) {
return VcsUserUtil.toExactString(user);
}
}));
result.addAll(ContainerUtil.map(users, user1 -> VcsUserUtil.toExactString(user1)));
}
else if (!user.equals(ME)) {
result.add(user);
@@ -92,24 +87,21 @@ public class VcsLogUserFilterImpl implements VcsLogUserFilter {
@Override
public boolean matches(@NotNull final VcsCommitMetadata commit) {
return ContainerUtil.exists(myUsers, new Condition<String>() {
@Override
public boolean value(String name) {
Set<VcsUser> users = getUsers(commit.getRoot(), name);
if (!users.isEmpty()) {
return users.contains(commit.getAuthor());
}
else if (!name.equals(ME)) {
String lowerUser = VcsUserUtil.nameToLowerCase(name);
boolean result = VcsUserUtil.nameToLowerCase(commit.getAuthor().getName()).equals(lowerUser) ||
VcsUserUtil.emailToLowerCase(commit.getAuthor().getEmail()).startsWith(lowerUser + "@");
if (result) {
LOG.warn("Unregistered author " + commit.getAuthor() + " for commit " + commit.getId().asString() + "; search pattern " + name);
}
return result;
}
return false;
return ContainerUtil.exists(myUsers, name -> {
Set<VcsUser> users = getUsers(commit.getRoot(), name);
if (!users.isEmpty()) {
return users.contains(commit.getAuthor());
}
else if (!name.equals(ME)) {
String lowerUser = VcsUserUtil.nameToLowerCase(name);
boolean result = VcsUserUtil.nameToLowerCase(commit.getAuthor().getName()).equals(lowerUser) ||
VcsUserUtil.emailToLowerCase(commit.getAuthor().getEmail()).startsWith(lowerUser + "@");
if (result) {
LOG.warn("Unregistered author " + commit.getAuthor() + " for commit " + commit.getId().asString() + "; search pattern " + name);
}
return result;
}
return false;
});
}
@@ -166,36 +166,30 @@ public class VcsStructureChooser extends DialogWrapper {
final MyCheckboxTreeCellRenderer cellRenderer =
new MyCheckboxTreeCellRenderer(mySelectionManager, myModulesSet, myProject, myTree, myRoots);
FileSystemTreeImpl fileSystemTree =
new FileSystemTreeImpl(myProject, descriptor, myTree, cellRenderer, null, new Convertor<TreePath, String>() {
@Override
public String convert(TreePath o) {
DefaultMutableTreeNode lastPathComponent = ((DefaultMutableTreeNode)o.getLastPathComponent());
Object uo = lastPathComponent.getUserObject();
if (uo instanceof FileNodeDescriptor) {
VirtualFile file = ((FileNodeDescriptor)uo).getElement().getFile();
String module = myModulesSet.get(file);
if (module != null) return module;
return file == null ? "" : file.getName();
}
return o.toString();
new FileSystemTreeImpl(myProject, descriptor, myTree, cellRenderer, null, o -> {
DefaultMutableTreeNode lastPathComponent = ((DefaultMutableTreeNode)o.getLastPathComponent());
Object uo = lastPathComponent.getUserObject();
if (uo instanceof FileNodeDescriptor) {
VirtualFile file = ((FileNodeDescriptor)uo).getElement().getFile();
String module = myModulesSet.get(file);
if (module != null) return module;
return file == null ? "" : file.getName();
}
return o.toString();
});
fileSystemTree.getTreeBuilder().getUi().setNodeDescriptorComparator(new Comparator<NodeDescriptor>() {
@Override
public int compare(NodeDescriptor o1, NodeDescriptor o2) {
if (o1 instanceof FileNodeDescriptor && o2 instanceof FileNodeDescriptor) {
VirtualFile f1 = ((FileNodeDescriptor)o1).getElement().getFile();
VirtualFile f2 = ((FileNodeDescriptor)o2).getElement().getFile();
fileSystemTree.getTreeBuilder().getUi().setNodeDescriptorComparator((o1, o2) -> {
if (o1 instanceof FileNodeDescriptor && o2 instanceof FileNodeDescriptor) {
VirtualFile f1 = ((FileNodeDescriptor)o1).getElement().getFile();
VirtualFile f2 = ((FileNodeDescriptor)o2).getElement().getFile();
boolean isDir1 = f1.isDirectory();
boolean isDir2 = f2.isDirectory();
if (isDir1 != isDir2) return isDir1 ? -1 : 1;
boolean isDir1 = f1.isDirectory();
boolean isDir2 = f2.isDirectory();
if (isDir1 != isDir2) return isDir1 ? -1 : 1;
return f1.getPath().compareToIgnoreCase(f2.getPath());
}
return o1.getIndex() - o2.getIndex();
return f1.getPath().compareToIgnoreCase(f2.getPath());
}
return o1.getIndex() - o2.getIndex();
});
new ClickListener() {
@@ -97,12 +97,7 @@ public class BranchesPanel extends JPanel {
List<RefGroup> groups = ContainerUtil.newArrayList();
for (RefGroup group : refGroups) {
if (group.isExpanded() || group.getRefs().size() == 1) {
groups.addAll(ContainerUtil.map(group.getRefs(), new Function<VcsRef, RefGroup>() {
@Override
public RefGroup fun(VcsRef ref) {
return new SingletonRefGroup(ref);
}
}));
groups.addAll(ContainerUtil.map(group.getRefs(), (Function<VcsRef, RefGroup>)ref -> new SingletonRefGroup(ref)));
}
else {
groups.add(group);
@@ -264,35 +264,22 @@ public class MainFrame extends JPanel implements DataProvider, Disposable {
List<VcsFullCommitDetails> details = myLog.getSelectedDetails();
if (details.size() > VcsLogUtil.MAX_SELECTED_COMMITS) return null;
return ContainerUtil
.map2Array(details, CommittedChangeListForRevision.class, new Function<VcsFullCommitDetails, CommittedChangeListForRevision>() {
@Override
public CommittedChangeListForRevision fun(@NotNull VcsFullCommitDetails details) {
return new CommittedChangeListForRevision(details.getSubject(), details.getFullMessage(),
VcsUserUtil.getShortPresentation(details.getCommitter()),
new Date(details.getCommitTime()), details.getChanges(),
convertToRevisionNumber(details.getId()));
}
});
.map2Array(details, CommittedChangeListForRevision.class,
details1 -> new CommittedChangeListForRevision(details1.getSubject(), details1.getFullMessage(),
VcsUserUtil.getShortPresentation(details1.getCommitter()),
new Date(details1.getCommitTime()), details1.getChanges(),
convertToRevisionNumber(details1.getId())));
}
else if (VcsDataKeys.VCS_REVISION_NUMBERS.is(dataId)) {
List<CommitId> hashes = myLog.getSelectedCommits();
if (hashes.size() > VcsLogUtil.MAX_SELECTED_COMMITS) return null;
return ArrayUtil.toObjectArray(ContainerUtil.map(hashes, new Function<CommitId, VcsRevisionNumber>() {
@Override
public VcsRevisionNumber fun(CommitId commitId) {
return convertToRevisionNumber(commitId.getHash());
}
}), VcsRevisionNumber.class);
return ArrayUtil
.toObjectArray(ContainerUtil.map(hashes, commitId -> convertToRevisionNumber(commitId.getHash())), VcsRevisionNumber.class);
}
else if (VcsDataKeys.VCS.is(dataId)) {
int[] selectedRows = myGraphTable.getSelectedRows();
if (selectedRows.length == 0 || selectedRows.length > VcsLogUtil.MAX_SELECTED_COMMITS) return null;
Set<VirtualFile> roots = ContainerUtil.map2Set(Ints.asList(selectedRows), new Function<Integer, VirtualFile>() {
@Override
public VirtualFile fun(@NotNull Integer row) {
return myGraphTable.getModel().getRoot(row);
}
});
Set<VirtualFile> roots = ContainerUtil.map2Set(Ints.asList(selectedRows), row -> myGraphTable.getModel().getRoot(row));
if (roots.size() == 1) {
return myLogData.getLogProvider(assertNotNull(getFirstItem(roots))).getSupportedVcs();
}
@@ -48,13 +48,10 @@ class ReferencePopupBuilder {
myUi = ui;
myRendererComponent = new SingleReferenceComponent(new VcsRefPainter(ui.getColorManager(), false));
myCellRenderer = new ListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
myRendererComponent.setReference((VcsRef)value);
myRendererComponent.setSelected(isSelected);
return myRendererComponent;
}
myCellRenderer = (list, value, index, isSelected, cellHasFocus) -> {
myRendererComponent.setReference((VcsRef)value);
myRendererComponent.setSelected(isSelected);
return myRendererComponent;
};
myList = createList(group);
@@ -188,12 +188,7 @@ public class GraphCommitCellRenderer extends ColoredTableCellRenderer {
}
private static List<VcsRef> getBranches(Collection<VcsRef> refs) {
return ContainerUtil.filter(refs, new Condition<VcsRef>() {
@Override
public boolean value(VcsRef ref) {
return ref.getType().isBranch();
}
});
return ContainerUtil.filter(refs, ref -> ref.getType().isBranch());
}
private static class PaintInfo {
@@ -78,12 +78,8 @@ public class GraphTableModel extends AbstractTableModel {
public int getRowOfCommitByPartOfHash(@NotNull String partialHash) {
final CommitIdByStringCondition hashByString = new CommitIdByStringCondition(partialHash);
CommitId commitId = myLogData.getHashMap().findCommitId(new Condition<CommitId>() {
@Override
public boolean value(CommitId commitId) {
return hashByString.value(commitId) && getRowOfCommit(commitId.getHash(), commitId.getRoot()) != -1;
}
});
CommitId commitId = myLogData.getHashMap().findCommitId(
commitId1 -> hashByString.value(commitId1) && getRowOfCommit(commitId1.getHash(), commitId1.getRoot()) != -1);
return commitId != null ? getRowOfCommit(commitId.getHash(), commitId.getRoot()) : -1;
}
@@ -188,42 +184,30 @@ public class GraphTableModel extends AbstractTableModel {
@NotNull
private Iterable<Integer> createRowsIterable(final int row, final int above, final int below, final int maxRows) {
return new Iterable<Integer>() {
@NotNull
return () -> new Iterator<Integer>() {
private int myRowIndex = Math.max(0, row - above);
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private int myRowIndex = Math.max(0, row - above);
public boolean hasNext() {
return myRowIndex < row + below && myRowIndex < maxRows;
}
@Override
public boolean hasNext() {
return myRowIndex < row + below && myRowIndex < maxRows;
}
@Override
public Integer next() {
int nextRow = myRowIndex;
myRowIndex++;
return getIdAtRow(nextRow);
}
@Override
public Integer next() {
int nextRow = myRowIndex;
myRowIndex++;
return getIdAtRow(nextRow);
}
@Override
public void remove() {
throw new UnsupportedOperationException("Removing elements is not supported.");
}
};
@Override
public void remove() {
throw new UnsupportedOperationException("Removing elements is not supported.");
}
};
}
@NotNull
public List<Integer> convertToCommitIds(@NotNull List<Integer> rows) {
return ContainerUtil.map(rows, new NotNullFunction<Integer, Integer>() {
@NotNull
@Override
public Integer fun(Integer row) {
return getIdAtRow(row);
}
});
return ContainerUtil.map(rows, (NotNullFunction<Integer, Integer>)row -> getIdAtRow(row));
}
}
@@ -61,12 +61,8 @@ public class StopWatch {
public void report() {
String message = myOperation + " took " + (System.currentTimeMillis() - myStartTime) + " ms";
if (myDurationPerRoot.size() > 1) {
message += "\n" + StringUtil.join(myDurationPerRoot.entrySet(), new Function<Map.Entry<VirtualFile, Long>, String>() {
@Override
public String fun(Map.Entry<VirtualFile, Long> entry) {
return " " + entry.getKey().getName() + ": " + entry.getValue() + " ms";
}
}, "\n");
message += "\n" + StringUtil.join(myDurationPerRoot.entrySet(),
entry -> " " + entry.getKey().getName() + ": " + entry.getValue() + " ms", "\n");
}
LOG.debug(message);
}