mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
IJPL-156647: merge: add statistics
GitOrigin-RevId: 8bb96df414312d166b070e9e90c874eef0b8c746
This commit is contained in:
committed by
intellij-monorepo-bot
parent
12a30d5198
commit
b6e7b4b06c
@@ -0,0 +1,36 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.diff.merge
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
internal class MergeStatisticsAggregator(
|
||||
val changes: Int,
|
||||
val autoResolvable: Int,
|
||||
val conflicts: Int,
|
||||
) {
|
||||
var unresolved: Int = -1
|
||||
val initialTimestamp: Long = System.currentTimeMillis()
|
||||
|
||||
private val resolvedByAiChanges = mutableSetOf<Int>()
|
||||
private val rolledBackAfterAI = mutableSetOf<Int>()
|
||||
private val undoneAfterAi = mutableSetOf<Int>()
|
||||
|
||||
fun resolvedByAi(): Int = resolvedByAiChanges.size
|
||||
fun rolledBackAfterAI(): Int = rolledBackAfterAI.size
|
||||
fun undoneAfterAI(): Int = undoneAfterAi.size
|
||||
|
||||
fun wasResolvedByAi(index: Int) {
|
||||
resolvedByAiChanges.add(index)
|
||||
}
|
||||
|
||||
fun wasRolledBackAfterAI(index: Int) {
|
||||
resolvedByAiChanges.remove(index)
|
||||
rolledBackAfterAI.add(index)
|
||||
}
|
||||
|
||||
fun wasUndoneAfterAI(index: Int) {
|
||||
resolvedByAiChanges.remove(index)
|
||||
undoneAfterAi.add(index)
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import com.intellij.diff.contents.DocumentContent;
|
||||
import com.intellij.diff.fragments.MergeLineFragment;
|
||||
import com.intellij.diff.requests.ContentDiffRequest;
|
||||
import com.intellij.diff.requests.SimpleDiffRequest;
|
||||
import com.intellij.diff.statistics.MergeStatisticsCollector;
|
||||
import com.intellij.diff.tools.holders.EditorHolderFactory;
|
||||
import com.intellij.diff.tools.holders.TextEditorHolder;
|
||||
import com.intellij.diff.tools.simple.ThreesideTextDiffViewerEx;
|
||||
@@ -118,6 +119,7 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
|
||||
private final Action myLeftResolveAction;
|
||||
private final Action myRightResolveAction;
|
||||
protected final Action myAcceptResolveAction;
|
||||
private MergeStatisticsAggregator myAggregator;
|
||||
|
||||
@NotNull protected final MergeContext myMergeContext;
|
||||
@NotNull protected final TextMergeRequest myMergeRequest;
|
||||
@@ -298,10 +300,17 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
|
||||
}
|
||||
|
||||
protected void doFinishMerge(@NotNull final MergeResult result) {
|
||||
if (result == MergeResult.RESOLVED) {
|
||||
logMergeFinished(MergeResultSource.DIALOG_BUTTON);
|
||||
}
|
||||
destroyChangedBlocks();
|
||||
myMergeContext.finishMerge(result);
|
||||
}
|
||||
|
||||
public enum MergeResultSource {
|
||||
DIALOG_BUTTON,
|
||||
NOTIFICATION
|
||||
}
|
||||
//
|
||||
// Diff
|
||||
//
|
||||
@@ -516,6 +525,15 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
|
||||
myCurrentIgnorePolicy = ignorePolicy;
|
||||
myResolveImportConflicts = getTextSettings().isAutoResolveImportConflicts();
|
||||
|
||||
// build initial statistics
|
||||
int autoResolvableChanges = ContainerUtil.count(getAllChanges(), c -> canResolveChangeAutomatically(c, ThreeSide.BASE));
|
||||
|
||||
myAggregator = new MergeStatisticsAggregator(
|
||||
getAllChanges().size(),
|
||||
autoResolvableChanges,
|
||||
getConflictsCount()
|
||||
);
|
||||
|
||||
if (myResolveImportConflicts) {
|
||||
List<TextMergeChange> importChanges = ContainerUtil.filter(getChanges(), change -> change.isImportChange());
|
||||
if (importChanges.size() != fragmentsWithMetadata.getFragments().size()) {
|
||||
@@ -729,6 +747,7 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
|
||||
@NlsSafe String message = XmlStringUtil.wrapInHtmlTag(DiffBundle.message("merge.all.changes.processed.message.text"), "a");
|
||||
DiffBalloons.showSuccessPopup(title, message, point, this, () -> {
|
||||
if (isDisposed() || myLoadingPanel.isLoading()) return;
|
||||
logMergeFinished(MergeResultSource.NOTIFICATION);
|
||||
destroyChangedBlocks();
|
||||
myMergeContext.finishMerge(MergeResult.RESOLVED);
|
||||
});
|
||||
@@ -825,6 +844,7 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
|
||||
@ApiStatus.Internal
|
||||
@RequiresEdt
|
||||
public void markChangeResolvedWithAI(@NotNull TextMergeChange change) {
|
||||
myAggregator.wasResolvedByAi(change.getIndex());
|
||||
change.markChangeResolvedWithAI();
|
||||
markChangeResolved(change);
|
||||
}
|
||||
@@ -889,7 +909,6 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
|
||||
@RequiresWriteLock
|
||||
void resetResolvedChange(TextMergeChange change) {
|
||||
if (!change.isResolved()) return;
|
||||
|
||||
MergeLineFragment changeFragment = change.getFragment();
|
||||
int startLine = changeFragment.getStartLine(ThreeSide.BASE);
|
||||
int endLine = changeFragment.getEndLine(ThreeSide.BASE);
|
||||
@@ -900,7 +919,9 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
|
||||
myModel.replaceChange(change.getIndex(), baseContent);
|
||||
|
||||
change.resetState();
|
||||
|
||||
if (change.isResolvedWithAI()) {
|
||||
myAggregator.wasRolledBackAfterAI(change.getIndex());
|
||||
}
|
||||
onChangeResolved(change);
|
||||
myModel.invalidateHighlighters(change.getIndex());
|
||||
}
|
||||
@@ -979,6 +1000,9 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
|
||||
TextMergeChange change = myAllMergeChanges.get(state.myIndex);
|
||||
|
||||
boolean wasResolved = change.isResolved();
|
||||
if (change.isResolvedWithAI()) {
|
||||
myAggregator.wasUndoneAfterAI(change.getIndex());
|
||||
}
|
||||
change.restoreState(state);
|
||||
if (wasResolved != change.isResolved()) onChangeResolved(change);
|
||||
}
|
||||
@@ -1278,6 +1302,11 @@ public class MergeThreesideViewer extends ThreesideTextDiffViewerEx {
|
||||
protected abstract boolean isEnabled(@NotNull TextMergeChange change);
|
||||
}
|
||||
|
||||
private void logMergeFinished(MergeResultSource source) {
|
||||
myAggregator.setUnresolved(getChanges().size());
|
||||
MergeStatisticsCollector.INSTANCE.logMergeFinished(myProject, source, myAggregator);
|
||||
}
|
||||
|
||||
private class IgnoreSelectedChangesSideAction extends ApplySelectedChangesActionBase {
|
||||
@NotNull private final Side mySide;
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.diff.statistics
|
||||
|
||||
import com.intellij.diff.merge.MergeStatisticsAggregator
|
||||
import com.intellij.diff.merge.MergeThreesideViewer.MergeResultSource
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
import com.intellij.internal.statistic.eventLog.events.EnumEventField
|
||||
import com.intellij.internal.statistic.eventLog.events.EventFields
|
||||
import com.intellij.internal.statistic.eventLog.events.IntEventField
|
||||
import com.intellij.internal.statistic.eventLog.events.VarargEventId
|
||||
import com.intellij.internal.statistic.service.fus.collectors.CounterUsagesCollector
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
internal object MergeStatisticsCollector : CounterUsagesCollector() {
|
||||
private val GROUP: EventLogGroup = EventLogGroup("vcs.merge", 1)
|
||||
|
||||
private val SOURCE: EnumEventField<MergeResultSource> = EventFields.Enum("source", MergeResultSource::class.java)
|
||||
private val CHANGES: IntEventField = EventFields.Int("changes")
|
||||
private val AUTO_RESOLVABLE = EventFields.Int("autoResolvable")
|
||||
private val CONFLICTS = EventFields.Int("conflicts")
|
||||
private val UNRESOLVED = EventFields.Int("unresolved")
|
||||
private val AI_RESOLVED = EventFields.Int("aiResolved")
|
||||
private val AI_ROLLED_BACK = EventFields.Int("rolledBackAfterAi")
|
||||
private val AI_UNDONE = EventFields.Int("undoneAfterAi")
|
||||
|
||||
private val FILE_MERGED_EVENT: VarargEventId = GROUP.registerVarargEvent("file.merged", CHANGES, EventFields.DurationMs, AUTO_RESOLVABLE, CONFLICTS, UNRESOLVED, AI_RESOLVED, AI_ROLLED_BACK, AI_UNDONE)
|
||||
|
||||
override fun getGroup(): EventLogGroup = GROUP
|
||||
|
||||
fun logMergeFinished(project: Project?, source: MergeResultSource, aggregator: MergeStatisticsAggregator) {
|
||||
FILE_MERGED_EVENT.log(project) {
|
||||
add(SOURCE.with(source))
|
||||
add(CHANGES.with(aggregator.changes))
|
||||
add(EventFields.DurationMs.with(System.currentTimeMillis() - aggregator.initialTimestamp))
|
||||
add(AUTO_RESOLVABLE.with(aggregator.autoResolvable))
|
||||
add(CONFLICTS.with(aggregator.conflicts))
|
||||
add(UNRESOLVED.with(aggregator.unresolved))
|
||||
add(AI_RESOLVED.with(aggregator.resolvedByAi()))
|
||||
add(AI_ROLLED_BACK.with(aggregator.rolledBackAfterAI()))
|
||||
add(AI_UNDONE.with(aggregator.undoneAfterAI()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -955,6 +955,7 @@
|
||||
implementation="com.intellij.ide.plugins.marketplace.statistics.validators.MarketplaceVendorsListValidator"/>
|
||||
<statistics.counterUsagesCollector implementationClass="com.intellij.codeInsight.template.impl.LiveTemplateRunLogger"/>
|
||||
<statistics.counterUsagesCollector implementationClass="com.intellij.openapi.diff.impl.DiffUsageTriggerCollector"/>
|
||||
<statistics.counterUsagesCollector implementationClass="com.intellij.diff.statistics.MergeStatisticsCollector"/>
|
||||
<statistics.counterUsagesCollector implementationClass="com.intellij.openapi.updateSettings.impl.IdeUpdateUsageTriggerCollector"/>
|
||||
<statistics.counterUsagesCollector implementationClass="com.intellij.openapi.application.ImportOldConfigsUsagesCollector"/>
|
||||
<statistics.counterUsagesCollector implementationClass="com.intellij.openapi.application.OldDirectoryCleaner$Stats"/>
|
||||
|
||||
Reference in New Issue
Block a user