From e84e27c43200936aa555072c54d39bc5db6bc56c Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Tue, 20 Jan 2015 16:39:36 +0300 Subject: [PATCH] vcs: scroll to line for annotate-from-annotate --- .../util/src/com/intellij/util/diff/Diff.java | 19 ++++++++----- .../openapi/vcs/AbstractVcsHelper.java | 2 ++ .../actions/AnnotateRevisionActionBase.java | 28 +++++++++++++++++-- .../vcs/impl/AbstractVcsHelperImpl.java | 6 +++- .../tests/git4idea/test/MockVcsHelper.java | 5 ++++ .../zmlx/hg4idea/test/HgMockVcsHelper.java | 4 +++ 6 files changed, 53 insertions(+), 11 deletions(-) diff --git a/platform/util/src/com/intellij/util/diff/Diff.java b/platform/util/src/com/intellij/util/diff/Diff.java index d41175fb3a98..db71cb5ccdcd 100644 --- a/platform/util/src/com/intellij/util/diff/Diff.java +++ b/platform/util/src/com/intellij/util/diff/Diff.java @@ -119,11 +119,13 @@ public class Diff { * @return translated line if the processing is ok; negative value otherwise */ public static int translateLine(@NotNull CharSequence before, @NotNull CharSequence after, int line) throws FilesTooBigForDiffException { + return translateLine(before, after, line, false); + } + + public static int translateLine(@NotNull CharSequence before, @NotNull CharSequence after, int line, boolean approximate) + throws FilesTooBigForDiffException { Change change = buildChanges(before, after); - if (change == null) { - return -1; - } - return translateLine(change, line); + return translateLine(change, line, approximate); } /** @@ -133,17 +135,20 @@ public class Diff { * @param line target line before change * @return translated line if the processing is ok; negative value otherwise */ - public static int translateLine(@NotNull Change change, int line) { + public static int translateLine(@Nullable Change change, int line) { + return translateLine(change, line, false); + } + + public static int translateLine(@Nullable Change change, int line, boolean approximate) { int result = line; Change currentChange = change; - while (currentChange != null) { if (line < currentChange.line0) break; if (line >= currentChange.line0 + currentChange.deleted) { result += currentChange.inserted - currentChange.deleted; } else { - return -1; + if (approximate) return currentChange.line1; } currentChange = currentChange.link; diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java b/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java index 0d76538eb978..1d2cadb6a532 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcsHelper.java @@ -71,6 +71,8 @@ public abstract class AbstractVcsHelper { public abstract void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs); + public abstract void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs, int line); + public abstract void showDifferences(final VcsFileRevision cvsVersionOn, final VcsFileRevision cvsVersionOn1, final File file); public abstract void showChangesListBrowser(CommittedChangeList changelist, @Nls String title); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java index 84331cdafdf5..15ed9ee1481c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateRevisionActionBase.java @@ -2,6 +2,8 @@ package com.intellij.openapi.vcs.actions; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; @@ -15,6 +17,8 @@ import com.intellij.openapi.vcs.impl.BackgroundableActionEnabledHandler; import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl; import com.intellij.openapi.vcs.impl.VcsBackgroundableActions; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.diff.Diff; +import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -60,7 +64,7 @@ public abstract class AnnotateRevisionActionBase extends AnAction { } @Override - public void actionPerformed(@NotNull AnActionEvent e) { + public void actionPerformed(@NotNull final AnActionEvent e) { final VcsFileRevision fileRevision = getFileRevision(e); final VirtualFile file = getFile(e); final AbstractVcs vcs = getVcs(e); @@ -68,10 +72,15 @@ public abstract class AnnotateRevisionActionBase extends AnAction { assert file != null; assert fileRevision != null; + final Editor editor = e.getData(CommonDataKeys.EDITOR); + final CharSequence oldContent = editor == null ? null : editor.getDocument().getImmutableCharSequence(); + final int oldLine = editor == null ? 0 : editor.getCaretModel().getLogicalPosition().line; + final AnnotationProvider annotationProvider = vcs.getCachingAnnotationProvider(); assert annotationProvider != null; final Ref fileAnnotationRef = new Ref(); + final Ref newLineRef = new Ref(); final Ref exceptionRef = new Ref(); final ProjectLevelVcsManagerImpl plVcsManager = (ProjectLevelVcsManagerImpl)ProjectLevelVcsManager.getInstance(vcs.getProject()); @@ -82,7 +91,20 @@ public abstract class AnnotateRevisionActionBase extends AnAction { BackgroundFromStartOption.getInstance()) { public void run(@NotNull ProgressIndicator indicator) { try { - fileAnnotationRef.set(annotationProvider.annotate(file, fileRevision)); + FileAnnotation fileAnnotation = annotationProvider.annotate(file, fileRevision); + + int newLine = oldLine; + if (oldContent != null) { + String content = fileAnnotation.getAnnotatedContent(); + try { + newLine = Diff.translateLine(oldContent, content, oldLine); + } + catch (FilesTooBigForDiffException ignore) { + } + } + + fileAnnotationRef.set(fileAnnotation); + newLineRef.set(newLine); } catch (VcsException e) { exceptionRef.set(e); @@ -103,7 +125,7 @@ public abstract class AnnotateRevisionActionBase extends AnAction { } if (fileAnnotationRef.isNull()) return; - AbstractVcsHelper.getInstance(myProject).showAnnotation(fileAnnotationRef.get(), file, vcs); + AbstractVcsHelper.getInstance(myProject).showAnnotation(fileAnnotationRef.get(), file, vcs, newLineRef.get()); } }); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java index 4dfbc258a191..c616c0d4eaf4 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/AbstractVcsHelperImpl.java @@ -375,7 +375,11 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper { } public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs) { - OpenFileDescriptor openFileDescriptor = new OpenFileDescriptor(myProject, file); + showAnnotation(annotation, file, vcs, 0); + } + + public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs, int line) { + OpenFileDescriptor openFileDescriptor = new OpenFileDescriptor(myProject, file, line, 0); Editor editor = FileEditorManager.getInstance(myProject).openTextEditor(openFileDescriptor, true); if (editor == null) { Messages.showMessageDialog(VcsBundle.message("message.text.cannot.open.editor", file.getPresentableUrl()), diff --git a/plugins/git4idea/tests/git4idea/test/MockVcsHelper.java b/plugins/git4idea/tests/git4idea/test/MockVcsHelper.java index 45f1e3965bea..c65a0f0ddaa8 100644 --- a/plugins/git4idea/tests/git4idea/test/MockVcsHelper.java +++ b/plugins/git4idea/tests/git4idea/test/MockVcsHelper.java @@ -67,6 +67,11 @@ public class MockVcsHelper extends AbstractVcsHelper { throw new UnsupportedOperationException(); } + @Override + public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs, int line) { + throw new UnsupportedOperationException(); + } + @Override public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs) { throw new UnsupportedOperationException(); diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java index 6e2414f53125..cad97728affa 100644 --- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java +++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgMockVcsHelper.java @@ -68,6 +68,10 @@ public class HgMockVcsHelper extends AbstractVcsHelper { return null; } + @Override + public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs, int line) { + } + @Override public void showAnnotation(FileAnnotation annotation, VirtualFile file, AbstractVcs vcs) { }