mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
IDEA-286601 vcs: inline diff from annotation
* Add generic implementation for all vcses GitOrigin-RevId: 4af117687a1d57fc586d4a094a6d37e3492f855c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7ea6f25dad
commit
33b92c8d65
@@ -0,0 +1,223 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.vcs.annotate;
|
||||
|
||||
import com.intellij.diff.comparison.ComparisonManager;
|
||||
import com.intellij.diff.comparison.ComparisonPolicy;
|
||||
import com.intellij.diff.fragments.DiffFragment;
|
||||
import com.intellij.diff.fragments.LineFragment;
|
||||
import com.intellij.diff.tools.util.text.LineOffsets;
|
||||
import com.intellij.diff.tools.util.text.LineOffsetsUtil;
|
||||
import com.intellij.openapi.diff.DiffNavigationContext;
|
||||
import com.intellij.openapi.progress.DumbProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.annotate.AnnotatedLineModificationDetails.InnerChange;
|
||||
import com.intellij.openapi.vcs.annotate.AnnotatedLineModificationDetails.InnerChangeType;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevision;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcsUtil.VcsImplUtil;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
public class DefaultLineModificationDetailsProvider implements FileAnnotation.LineModificationDetailsProvider {
|
||||
@NotNull private final FileAnnotation myAnnotation;
|
||||
@NotNull private final FilePath myFilePath;
|
||||
@NotNull private final FileAnnotation.CurrentFileRevisionProvider myCurrentRevisionProvider;
|
||||
@NotNull private final FileAnnotation.PreviousFileRevisionProvider myPreviousRevisionProvider;
|
||||
|
||||
private DefaultLineModificationDetailsProvider(@NotNull FileAnnotation annotation,
|
||||
@NotNull FilePath filePath,
|
||||
@NotNull FileAnnotation.CurrentFileRevisionProvider currentRevisionProvider,
|
||||
@NotNull FileAnnotation.PreviousFileRevisionProvider previousRevisionProvider) {
|
||||
myAnnotation = annotation;
|
||||
myFilePath = filePath;
|
||||
myCurrentRevisionProvider = currentRevisionProvider;
|
||||
myPreviousRevisionProvider = previousRevisionProvider;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static FileAnnotation.LineModificationDetailsProvider create(@NotNull FileAnnotation annotation) {
|
||||
VirtualFile file = annotation.getFile();
|
||||
if (file == null) return null;
|
||||
|
||||
FileAnnotation.CurrentFileRevisionProvider currentRevisionProvider = annotation.getCurrentFileRevisionProvider();
|
||||
FileAnnotation.PreviousFileRevisionProvider previousRevisionProvider = annotation.getPreviousFileRevisionProvider();
|
||||
if (currentRevisionProvider == null || previousRevisionProvider == null) return null;
|
||||
|
||||
FilePath filePath = VcsUtil.getFilePath(file);
|
||||
return new DefaultLineModificationDetailsProvider(annotation, filePath, currentRevisionProvider, previousRevisionProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable AnnotatedLineModificationDetails getDetails(int lineNumber) throws VcsException {
|
||||
String annotatedContent = myAnnotation.getAnnotatedContent();
|
||||
if (annotatedContent == null) return null;
|
||||
|
||||
VcsFileRevision afterRevision = myCurrentRevisionProvider.getRevision(lineNumber);
|
||||
String afterContent = loadRevision(myAnnotation.getProject(), afterRevision, myFilePath);
|
||||
if (afterContent == null) return null;
|
||||
|
||||
VcsFileRevision beforeRevision = myPreviousRevisionProvider.getPreviousRevision(lineNumber);
|
||||
String beforeContent = loadRevision(myAnnotation.getProject(), beforeRevision, myFilePath);
|
||||
if (beforeContent == null) return null;
|
||||
|
||||
LineOffsets offsets = LineOffsetsUtil.create(annotatedContent);
|
||||
String originalLine = getLine(annotatedContent, offsets, lineNumber);
|
||||
|
||||
return createDetailsFor(beforeContent, afterContent, originalLine);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String loadRevision(@Nullable Project project,
|
||||
@Nullable VcsFileRevision revision,
|
||||
@NotNull FilePath filePath) throws VcsException {
|
||||
try {
|
||||
if (revision == null) return null;
|
||||
byte[] bytes = revision.loadContent();
|
||||
if (bytes == null) return null;
|
||||
String content = VcsImplUtil.loadTextFromBytes(project, bytes, filePath);
|
||||
return StringUtil.convertLineSeparators(content);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static AnnotatedLineModificationDetails createDetailsFor(@NotNull String beforeContent,
|
||||
@NotNull String afterContent,
|
||||
@NotNull String originalLine) {
|
||||
List<LineFragment> fragments = compareContents(beforeContent, afterContent);
|
||||
|
||||
LineOffsets afterLineOffsets = LineOffsetsUtil.create(afterContent);
|
||||
int originalLineNumber = findOriginalLine(afterContent, afterLineOffsets, originalLine, fragments);
|
||||
if (originalLineNumber == -1) {
|
||||
return null; // line not found
|
||||
}
|
||||
|
||||
String lineContentAfter = getLine(afterContent, afterLineOffsets, originalLineNumber);
|
||||
|
||||
if (StringUtil.isEmptyOrSpaces(lineContentAfter)) {
|
||||
return createNewLineDetails(lineContentAfter); // empty lines are always new, for simplicity
|
||||
}
|
||||
|
||||
return createFragmentDetails(lineContentAfter, afterLineOffsets, fragments, originalLineNumber);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AnnotatedLineModificationDetails createDetailsFor(@Nullable String beforeContent,
|
||||
@NotNull String afterContent,
|
||||
int originalLineNumber) {
|
||||
LineOffsets afterLineOffsets = LineOffsetsUtil.create(afterContent);
|
||||
String lineContentAfter = getLine(afterContent, afterLineOffsets, originalLineNumber);
|
||||
|
||||
if (beforeContent == null) {
|
||||
return createNewLineDetails(lineContentAfter); // whole file is new
|
||||
}
|
||||
|
||||
if (StringUtil.isEmptyOrSpaces(lineContentAfter)) {
|
||||
return createNewLineDetails(lineContentAfter); // empty lines are always new, for simplicity
|
||||
}
|
||||
|
||||
List<LineFragment> fragments = compareContents(beforeContent, afterContent);
|
||||
return createFragmentDetails(lineContentAfter, afterLineOffsets, fragments, originalLineNumber);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static AnnotatedLineModificationDetails createFragmentDetails(@NotNull String lineContentAfter,
|
||||
@NotNull LineOffsets afterLineOffsets,
|
||||
@NotNull List<LineFragment> fragments,
|
||||
int originalLineNumber) {
|
||||
LineFragment lineFragment = ContainerUtil.find(fragments.iterator(), fragment -> {
|
||||
return fragment.getStartLine2() <= originalLineNumber && originalLineNumber < fragment.getEndLine2();
|
||||
});
|
||||
if (lineFragment == null) return null; // line unmodified
|
||||
|
||||
if (lineFragment.getStartLine1() == lineFragment.getEndLine1()) {
|
||||
return createNewLineDetails(lineContentAfter); // whole line is new
|
||||
}
|
||||
|
||||
List<DiffFragment> innerFragments = lineFragment.getInnerFragments();
|
||||
if (innerFragments == null) {
|
||||
return createModifiedLineDetails(lineContentAfter); // whole line is modified
|
||||
}
|
||||
|
||||
int lineStart = afterLineOffsets.getLineStart(originalLineNumber);
|
||||
int lineEnd = afterLineOffsets.getLineEnd(originalLineNumber);
|
||||
int windowStart = lineStart - lineFragment.getStartOffset2();
|
||||
int windowEnd = lineEnd - lineFragment.getStartOffset2();
|
||||
int lineLength = lineEnd - lineStart;
|
||||
|
||||
List<InnerChange> changes = new ArrayList<>();
|
||||
for (DiffFragment innerFragment : innerFragments) {
|
||||
if (innerFragment.getEndOffset2() < windowStart || innerFragment.getStartOffset2() > windowEnd) continue;
|
||||
int start = Math.max(0, innerFragment.getStartOffset2() - windowStart);
|
||||
int end = Math.min(lineLength, innerFragment.getEndOffset2() - windowStart);
|
||||
InnerChangeType type = start == end ? InnerChangeType.DELETED
|
||||
: innerFragment.getStartOffset1() != innerFragment.getEndOffset1() ? InnerChangeType.MODIFIED
|
||||
: InnerChangeType.INSERTED;
|
||||
changes.add(new InnerChange(start, end, type));
|
||||
}
|
||||
|
||||
return new AnnotatedLineModificationDetails(lineContentAfter, changes);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static AnnotatedLineModificationDetails createNewLineDetails(@NotNull String lineContentAfter) {
|
||||
InnerChange innerChange = new InnerChange(0, lineContentAfter.length(), InnerChangeType.INSERTED);
|
||||
return new AnnotatedLineModificationDetails(lineContentAfter, singletonList(innerChange));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static AnnotatedLineModificationDetails createModifiedLineDetails(@NotNull String lineContentAfter) {
|
||||
InnerChange innerChange = new InnerChange(0, lineContentAfter.length(), InnerChangeType.MODIFIED);
|
||||
return new AnnotatedLineModificationDetails(lineContentAfter, singletonList(innerChange));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<LineFragment> compareContents(@NotNull String beforeContent, @NotNull String afterContent) {
|
||||
ProgressIndicator indicator = ObjectUtils.chooseNotNull(ProgressIndicatorProvider.getGlobalProgressIndicator(),
|
||||
DumbProgressIndicator.INSTANCE);
|
||||
return ComparisonManager.getInstance().compareLinesInner(beforeContent, afterContent, ComparisonPolicy.DEFAULT, indicator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for affected line in content after the commit.
|
||||
*
|
||||
* @see DiffNavigationContext
|
||||
*/
|
||||
private static int findOriginalLine(@NotNull String afterContent,
|
||||
@NotNull LineOffsets afterLineOffsets,
|
||||
@NotNull String originalLine,
|
||||
@NotNull List<LineFragment> fragments) {
|
||||
for (LineFragment fragment : fragments) {
|
||||
for (int i = fragment.getStartLine2(); i < fragment.getEndLine2(); i++) {
|
||||
String line = getLine(afterContent, afterLineOffsets, i);
|
||||
if (StringUtil.equalsIgnoreWhitespaces(line, originalLine)) return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // line not found
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getLine(@NotNull String text, @NotNull LineOffsets lineOffsets, int line) {
|
||||
int lineStart = lineOffsets.getLineStart(line);
|
||||
int lineEnd = lineOffsets.getLineEnd(line);
|
||||
return text.substring(lineStart, lineEnd);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,23 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package git4idea.annotate;
|
||||
|
||||
import com.intellij.diff.comparison.ComparisonManager;
|
||||
import com.intellij.diff.comparison.ComparisonPolicy;
|
||||
import com.intellij.diff.fragments.DiffFragment;
|
||||
import com.intellij.diff.fragments.LineFragment;
|
||||
import com.intellij.diff.tools.util.text.LineOffsets;
|
||||
import com.intellij.diff.tools.util.text.LineOffsetsUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.DumbProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.*;
|
||||
import com.intellij.openapi.vcs.annotate.*;
|
||||
import com.intellij.openapi.vcs.annotate.AnnotatedLineModificationDetails.InnerChange;
|
||||
import com.intellij.openapi.vcs.annotate.AnnotatedLineModificationDetails.InnerChangeType;
|
||||
import com.intellij.openapi.vcs.changes.ContentRevision;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevision;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.openapi.vcs.impl.AbstractVcsHelperImpl;
|
||||
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.concurrency.EdtExecutorService;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
@@ -38,7 +25,6 @@ import com.intellij.vcs.log.Hash;
|
||||
import com.intellij.vcs.log.VcsUser;
|
||||
import com.intellij.vcs.log.impl.*;
|
||||
import com.intellij.vcs.log.util.VcsUserUtil;
|
||||
import com.intellij.vcsUtil.VcsImplUtil;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import git4idea.GitContentRevision;
|
||||
import git4idea.GitFileRevision;
|
||||
@@ -56,12 +42,9 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
public final class GitFileAnnotation extends FileAnnotation {
|
||||
private static final Logger LOG = Logger.getInstance(GitFileAnnotation.class);
|
||||
|
||||
@@ -626,86 +609,13 @@ public final class GitFileAnnotation extends FileAnnotation {
|
||||
LineInfo lineInfo = getLineInfo(lineNumber);
|
||||
if (lineInfo == null) return null;
|
||||
|
||||
String afterContent = loadRevision(lineInfo.getFileRevision());
|
||||
String afterContent = DefaultLineModificationDetailsProvider.loadRevision(myProject, lineInfo.getFileRevision(), myFilePath);
|
||||
if (afterContent == null) return null;
|
||||
|
||||
int originalLineNumber = lineInfo.getOriginalLineNumber() - 1; // in 'afterContent'
|
||||
LineOffsets afterLineOffsets = LineOffsetsUtil.create(afterContent);
|
||||
int lineStart = afterLineOffsets.getLineStart(originalLineNumber);
|
||||
int lineEnd = afterLineOffsets.getLineEnd(originalLineNumber);
|
||||
String lineContentAfter = afterContent.substring(lineStart, lineEnd);
|
||||
String beforeContent = DefaultLineModificationDetailsProvider.loadRevision(myProject, lineInfo.getPreviousFileRevision(), myFilePath);
|
||||
|
||||
if (StringUtil.isEmptyOrSpaces(lineContentAfter)) {
|
||||
return createNewLineDetails(lineContentAfter); // empty lines are always new, for simplicity
|
||||
}
|
||||
|
||||
String beforeContent = loadRevision(lineInfo.getPreviousFileRevision());
|
||||
if (beforeContent == null) {
|
||||
return createNewLineDetails(lineContentAfter); // whole file is new
|
||||
}
|
||||
|
||||
ProgressIndicator indicator = ObjectUtils.chooseNotNull(ProgressIndicatorProvider.getGlobalProgressIndicator(),
|
||||
DumbProgressIndicator.INSTANCE);
|
||||
List<LineFragment> fragments = ComparisonManager.getInstance().compareLinesInner(beforeContent, afterContent,
|
||||
ComparisonPolicy.DEFAULT, indicator);
|
||||
|
||||
LineFragment lineFragment = ContainerUtil.find(fragments.iterator(), fragment -> {
|
||||
return fragment.getStartLine2() <= originalLineNumber && originalLineNumber < fragment.getEndLine2();
|
||||
});
|
||||
if (lineFragment == null) return null; // line unmodified
|
||||
|
||||
|
||||
if (lineFragment.getStartLine1() == lineFragment.getEndLine1()) {
|
||||
return createNewLineDetails(lineContentAfter); // whole line is new
|
||||
}
|
||||
|
||||
List<DiffFragment> innerFragments = lineFragment.getInnerFragments();
|
||||
if (innerFragments == null) {
|
||||
return createModifiedLineDetails(lineContentAfter); // whole line is modified
|
||||
}
|
||||
|
||||
int windowStart = lineStart - lineFragment.getStartOffset2();
|
||||
int windowEnd = lineEnd - lineFragment.getStartOffset2();
|
||||
int lineLength = lineEnd - lineStart;
|
||||
|
||||
List<InnerChange> changes = new ArrayList<>();
|
||||
for (DiffFragment innerFragment : innerFragments) {
|
||||
if (innerFragment.getEndOffset2() < windowStart || innerFragment.getStartOffset2() > windowEnd) continue;
|
||||
int start = Math.max(0, innerFragment.getStartOffset2() - windowStart);
|
||||
int end = Math.min(lineLength, innerFragment.getEndOffset2() - windowStart);
|
||||
InnerChangeType type = start == end ? InnerChangeType.DELETED
|
||||
: innerFragment.getStartOffset1() != innerFragment.getEndOffset1() ? InnerChangeType.MODIFIED
|
||||
: InnerChangeType.INSERTED;
|
||||
changes.add(new InnerChange(start, end, type));
|
||||
}
|
||||
|
||||
return new AnnotatedLineModificationDetails(lineContentAfter, changes);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AnnotatedLineModificationDetails createNewLineDetails(@NotNull String lineContentAfter) {
|
||||
InnerChange innerChange = new InnerChange(0, lineContentAfter.length(), InnerChangeType.INSERTED);
|
||||
return new AnnotatedLineModificationDetails(lineContentAfter, singletonList(innerChange));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AnnotatedLineModificationDetails createModifiedLineDetails(@NotNull String lineContentAfter) {
|
||||
InnerChange innerChange = new InnerChange(0, lineContentAfter.length(), InnerChangeType.MODIFIED);
|
||||
return new AnnotatedLineModificationDetails(lineContentAfter, singletonList(innerChange));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String loadRevision(@Nullable VcsFileRevision revision) throws VcsException {
|
||||
try {
|
||||
if (revision == null) return null;
|
||||
byte[] bytes = revision.loadContent();
|
||||
if (bytes == null) return null;
|
||||
String content = VcsImplUtil.loadTextFromBytes(myProject, bytes, myFilePath);
|
||||
return StringUtil.convertLineSeparators(content);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new VcsException(e);
|
||||
}
|
||||
int originalLineNumber = lineInfo.getOriginalLineNumber() - 1;
|
||||
return DefaultLineModificationDetailsProvider.createDetailsFor(beforeContent, afterContent, originalLineNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,12 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.vcs.VcsBundle;
|
||||
import com.intellij.openapi.vcs.VcsKey;
|
||||
import com.intellij.openapi.vcs.annotate.FileAnnotation;
|
||||
import com.intellij.openapi.vcs.annotate.LineAnnotationAspect;
|
||||
import com.intellij.openapi.vcs.annotate.LineAnnotationAspectAdapter;
|
||||
import com.intellij.openapi.vcs.annotate.ShowAllAffectedGenericAction;
|
||||
import com.intellij.openapi.vcs.annotate.*;
|
||||
import com.intellij.openapi.vcs.history.VcsFileRevision;
|
||||
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.openapi.vcs.annotate.AnnotationTooltipBuilder;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -66,7 +62,7 @@ public class HgAnnotation extends FileAnnotation {
|
||||
|
||||
@Override
|
||||
public LineAnnotationAspect[] getAspects() {
|
||||
return new LineAnnotationAspect[] {
|
||||
return new LineAnnotationAspect[]{
|
||||
revisionAnnotationAspect,
|
||||
dateAnnotationAspect,
|
||||
userAnnotationAspect
|
||||
@@ -88,7 +84,7 @@ public class HgAnnotation extends FileAnnotation {
|
||||
@Nls
|
||||
@Nullable
|
||||
private String getToolTip(int lineNumber, boolean asHtml) {
|
||||
if ( myLines.size() <= lineNumber || lineNumber < 0 ) {
|
||||
if (myLines.size() <= lineNumber || lineNumber < 0) {
|
||||
return null;
|
||||
}
|
||||
HgAnnotationLine info = myLines.get(lineNumber);
|
||||
@@ -194,8 +190,8 @@ public class HgAnnotation extends FileAnnotation {
|
||||
}
|
||||
HgAnnotationLine annotationLine = myLines.get(lineNumber);
|
||||
return myAspectType == FIELD.REVISION
|
||||
? annotationLine.getVcsRevisionNumber().asString()
|
||||
: annotationLine.get(myAspectType).toString();
|
||||
? annotationLine.getVcsRevisionNumber().asString()
|
||||
: annotationLine.get(myAspectType).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -225,4 +221,10 @@ public class HgAnnotation extends FileAnnotation {
|
||||
public VirtualFile getFile() {
|
||||
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(myFile.getFile());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public LineModificationDetailsProvider getLineModificationDetailsProvider() {
|
||||
return DefaultLineModificationDetailsProvider.create(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.xml.util.XmlStringUtil.escapeString;
|
||||
import static com.intellij.openapi.vcs.annotate.AnnotationTooltipBuilder.buildSimpleTooltip;
|
||||
import static com.intellij.xml.util.XmlStringUtil.escapeString;
|
||||
|
||||
public abstract class BaseSvnFileAnnotation extends FileAnnotation {
|
||||
private final String myContents;
|
||||
@@ -192,7 +192,7 @@ public abstract class BaseSvnFileAnnotation extends FileAnnotation {
|
||||
@Override
|
||||
@Nullable
|
||||
public AnnotationSourceSwitcher getAnnotationSourceSwitcher() {
|
||||
if (! myShowMergeSources) return null;
|
||||
if (!myShowMergeSources) return null;
|
||||
return new AnnotationSourceSwitcher() {
|
||||
@Override
|
||||
@NotNull
|
||||
@@ -336,4 +336,10 @@ public abstract class BaseSvnFileAnnotation extends FileAnnotation {
|
||||
public VcsRevisionNumber getCurrentRevision() {
|
||||
return myBaseRevision;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public LineModificationDetailsProvider getLineModificationDetailsProvider() {
|
||||
return DefaultLineModificationDetailsProvider.create(this);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user