From 5f44d7781fe95d0e0d22de63539ec44c46246792 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Sat, 11 Jan 2014 20:03:49 +0400 Subject: [PATCH] [diff] IDEA-77540 Go To Source from vcs diff Go To Source uses the getOpenFileDescriptor() returned by DiffContent, but it is null for BinaryContent & SimpleContent, both used from different places of the VCS history. * Implement it for BinaryContent: - get the file by path if exists - supply the Project to the constructor, deprecate other constructors. * SimpleContent is too general thing and is used everywhere, so for certain VCS operations create a separate extension - OpenFileCapableSimpleContent which behaves the same way: searches the virtual file by path. KNOWN LIMITATION: current implementation navigates to the same offset, no conversion is made if the file is different from the current version. --- .../intellij/openapi/diff/BinaryContent.java | 39 ++++++++++----- .../intellij/diff/FileAwareSimpleContent.java | 48 +++++++++++++++++++ .../vcs/actions/DiffActionExecutor.java | 3 +- .../actions/ChangeDiffRequestPresentable.java | 8 ++-- .../openapi/vcs/history/VcsHistoryUtil.java | 4 +- 5 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 platform/vcs-impl/src/com/intellij/diff/FileAwareSimpleContent.java diff --git a/platform/platform-api/src/com/intellij/openapi/diff/BinaryContent.java b/platform/platform-api/src/com/intellij/openapi/diff/BinaryContent.java index 849dd4cbc4d8..b73c59e3ab2f 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/BinaryContent.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/BinaryContent.java @@ -20,6 +20,8 @@ import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.UIBasedFileType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; @@ -34,9 +36,10 @@ import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; /** - * Represents bytes as content. May has text representaion. + * A {@link DiffContent} represented as a byte array. It still contain a text though. */ public class BinaryContent extends DiffContent { + @NotNull private final Project myProject; @NotNull private final FileType myFileType; private final byte[] myBytes; @@ -45,11 +48,12 @@ public class BinaryContent extends DiffContent { private String myFilePath; /** - * @param charset use to convert bytes to String. null means bytes can't be converted to text. - * Has no sense if fileType.isBinary() + * @param charset use to convert bytes to String. null means bytes can't be converted to text. Has no sense if fileType.isBinary() * @param fileType type of content */ - public BinaryContent(byte[] bytes, Charset charset, @NotNull FileType fileType) { + public BinaryContent(@NotNull Project project, byte[] bytes, @Nullable Charset charset, @NotNull FileType fileType, + @Nullable String filePath) { + myProject = project; myFileType = fileType; myBytes = bytes; if (fileType.isBinary()) { @@ -58,11 +62,21 @@ public class BinaryContent extends DiffContent { else { myCharset = charset; } + myFilePath = filePath; + } + + /** + * @deprecated to remove in IDEA 14. Use {@link #BinaryContent(Project, byte[], Charset, FileType, String)}. + */ + public BinaryContent(byte[] bytes, Charset charset, @NotNull FileType fileType) { + this(bytes, charset, fileType, null); } + /** + * @deprecated to remove in IDEA 14. Use {@link #BinaryContent(Project, byte[], Charset, FileType, String)}. + */ public BinaryContent(byte[] bytes, Charset charset, @NotNull FileType fileType, String filePath) { - this(bytes, charset, fileType); - myFilePath = filePath; + this(ProjectManager.getInstance().getDefaultProject(), bytes, charset, fileType, filePath); } @Override @@ -95,19 +109,22 @@ public class BinaryContent extends DiffContent { return myDocument; } - /** - * @return null - */ @Override public OpenFileDescriptor getOpenFileDescriptor(int offset) { - return null; + VirtualFile file = findVirtualFile(); + return file == null ? null : new OpenFileDescriptor(myProject, file, offset); + } + + @Nullable + private VirtualFile findVirtualFile() { + return LocalFileSystem.getInstance().findFileByIoFile(new File(myFilePath)); } @Override @Nullable public VirtualFile getFile() { if (myFileType instanceof UIBasedFileType) { - final VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(new File(myFilePath)); + final VirtualFile file = findVirtualFile(); if (file != null) { final LightVirtualFile lightFile = new LightVirtualFile(file, new String(myBytes), 1); lightFile.setOriginalFile(file); diff --git a/platform/vcs-impl/src/com/intellij/diff/FileAwareSimpleContent.java b/platform/vcs-impl/src/com/intellij/diff/FileAwareSimpleContent.java new file mode 100644 index 000000000000..79988fc340d0 --- /dev/null +++ b/platform/vcs-impl/src/com/intellij/diff/FileAwareSimpleContent.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.diff; + +import com.intellij.openapi.diff.SimpleContent; +import com.intellij.openapi.fileEditor.OpenFileDescriptor; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * A {@link SimpleContent} which content is retrieved from a file which exists or existed in the project. + */ +public class FileAwareSimpleContent extends SimpleContent { + + @NotNull private final Project myProject; + @NotNull private final FilePath myFilePath; + + public FileAwareSimpleContent(@NotNull Project project, @NotNull FilePath filePath, @NotNull String text, @Nullable FileType type) { + super(text, type); + myProject = project; + myFilePath = filePath; + } + + @Override + public OpenFileDescriptor getOpenFileDescriptor(int offset) { + VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(myFilePath.getIOFile()); + return file == null ? null : new OpenFileDescriptor(myProject, file, offset); + } + +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/DiffActionExecutor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/DiffActionExecutor.java index 68720739c065..704b4b5eb8b1 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/DiffActionExecutor.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/DiffActionExecutor.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.vcs.actions; +import com.intellij.diff.FileAwareSimpleContent; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diff.*; import com.intellij.openapi.editor.Document; @@ -86,7 +87,7 @@ public abstract class DiffActionExecutor { if (content == null) { throw new VcsException("Failed to load content"); } - return new SimpleContent(content, mySelectedFile.getFileType()); + return new FileAwareSimpleContent(myProject, fileRevision.getFile(), content, mySelectedFile.getFileType()); } return null; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java index 948ef892b8f3..f2678bd258d0 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java @@ -16,6 +16,7 @@ package com.intellij.openapi.vcs.changes.actions; import com.intellij.CommonBundle; +import com.intellij.diff.FileAwareSimpleContent; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.DiffContent; @@ -150,8 +151,9 @@ public class ChangeDiffRequestPresentable implements DiffRequestPresentable { final VirtualFile vFile = current.getVirtualFile(); return vFile != null ? new FileContent(myProject, vFile) : new SimpleContent(""); } + FilePath filePath = revision.getFile(); if (revision instanceof BinaryContentRevision) { - final String name = revision.getFile().getName(); + final String name = filePath.getName(); try { return FileContent.createFromTempFile(myProject, name, name, ((BinaryContentRevision)revision).getBinaryContent()); } @@ -188,8 +190,8 @@ public class ChangeDiffRequestPresentable implements DiffRequestPresentable { } SimpleContent content = revisionContent == null ? new SimpleContent("") - : new SimpleContent(revisionContent, revision.getFile().getFileType()); - VirtualFile vFile = revision.getFile().getVirtualFile(); + : new FileAwareSimpleContent(myProject, filePath, revisionContent, filePath.getFileType()); + VirtualFile vFile = filePath.getVirtualFile(); if (vFile != null) { content.setCharset(vFile.getCharset()); content.setBOM(vFile.getBOM()); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java index 3fba542ae1e6..7711dd3ac394 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/VcsHistoryUtil.java @@ -186,9 +186,9 @@ public class VcsHistoryUtil { return CharsetToolkit.bytesToString(bytes, e.getDefaultCharset()); } - private static DiffContent createContent(Project project, byte[] content1, VcsFileRevision revision, Document doc, Charset charset, FileType fileType, String filePath) { + private static DiffContent createContent(@NotNull Project project, byte[] content1, VcsFileRevision revision, Document doc, Charset charset, FileType fileType, String filePath) { if (isCurrent(revision) && (doc != null)) { return new DocumentContent(project, doc); } - return new BinaryContent(content1, charset, fileType, filePath); + return new BinaryContent(project, content1, charset, fileType, filePath); } private static boolean isCurrent(VcsFileRevision revision) {