diff: allow to assign FileType from unshelve diff
authorAleksey Pivovarov <AMPivovarov@gmail.com>
Mon, 17 Aug 2015 14:48:59 +0000 (17:48 +0300)
committerAleksey Pivovarov <AMPivovarov@gmail.com>
Wed, 19 Aug 2015 17:47:07 +0000 (20:47 +0300)
* allow to drop caches and reload DiffRequest
* use reloadDiffRequest() after assigning FileType, as some DiffContents could cache old value, and DiffTools skip them.

platform/diff-api/src/com/intellij/diff/requests/ComponentDiffRequest.java [new file with mode: 0644]
platform/diff-impl/src/com/intellij/diff/DiffContextEx.java
platform/diff-impl/src/com/intellij/diff/impl/CacheDiffRequestChainProcessor.java
platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java
platform/diff-impl/src/com/intellij/diff/requests/UnknownFileTypeDiffRequest.java [new file with mode: 0644]
platform/diff-impl/src/com/intellij/diff/tools/ErrorDiffTool.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/CacheChangeProcessor.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/PatchDiffRequestFactory.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/TextFilePatchInProgress.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/DiffShelvedChangesAction.java

diff --git a/platform/diff-api/src/com/intellij/diff/requests/ComponentDiffRequest.java b/platform/diff-api/src/com/intellij/diff/requests/ComponentDiffRequest.java
new file mode 100644 (file)
index 0000000..90b2d86
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2015 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.requests;
+
+import com.intellij.diff.DiffContext;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+public abstract class ComponentDiffRequest extends DiffRequest {
+  @NotNull
+  public abstract JComponent getComponent(@NotNull DiffContext context);
+}
index 2e6550d7b9f057e2080cb8312e34d454c18286c9..a9369b9bfcac07171238b2e562b145eeba3794f6 100644 (file)
@@ -18,8 +18,17 @@ package com.intellij.diff;
 public abstract class DiffContextEx extends DiffContext {
   /*
    * Reopen current DiffRequest.
+   *
    * perform the same procedure as on switching between DiffRequests or between DiffViewers.
    * this can be used, if some change in request or settings was made, and we need to reopen DiffViewer to apply them.
    */
+  public abstract void reopenDiffRequest();
+
+  /*
+   * Drop cached DiffRequest version (if any) and reopen current DiffRequest.
+   *
+   * perform the same procedure as on opening DiffRequests for the first time.
+   * this can be used, if some change in request or settings was made, and we need to reload DiffRequest to apply them.
+   */
   public abstract void reloadDiffRequest();
 }
index f44cd17276aa9bc72453a93d365ea614121f356c..8e37522288eb452a1315abb1769cc3248b12311c 100644 (file)
@@ -33,7 +33,6 @@ import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.util.ProgressWindow;
 import com.intellij.openapi.project.DumbAwareAction;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Disposer;
 import com.intellij.util.Consumer;
 import com.intellij.util.Function;
 import com.intellij.util.containers.ContainerUtil;
@@ -64,8 +63,18 @@ public abstract class CacheDiffRequestChainProcessor extends DiffRequestProcesso
   // Update
   //
 
+  @Override
+  protected void reloadRequest() {
+    updateRequest(true, false, null);
+  }
+
   @CalledInAwt
   public void updateRequest(final boolean force, @Nullable final ScrollToPolicy scrollToChangePolicy) {
+    updateRequest(force, true, scrollToChangePolicy);
+  }
+
+  @CalledInAwt
+  public void updateRequest(final boolean force, boolean useCache, @Nullable final ScrollToPolicy scrollToChangePolicy) {
     List<? extends DiffRequestProducer> requests = myRequestChain.getRequests();
     int index = myRequestChain.getIndex();
     if (index < 0 || index >= requests.size()) {
@@ -75,7 +84,7 @@ public abstract class CacheDiffRequestChainProcessor extends DiffRequestProcesso
 
     final DiffRequestProducer producer = requests.get(index);
 
-    DiffRequest request = loadRequestFast(producer);
+    DiffRequest request = loadRequestFast(producer, useCache);
     if (request != null) {
       applyRequest(request, force, scrollToChangePolicy);
       return;
@@ -107,7 +116,8 @@ public abstract class CacheDiffRequestChainProcessor extends DiffRequestProcesso
   }
 
   @Nullable
-  protected DiffRequest loadRequestFast(@NotNull DiffRequestProducer producer) {
+  protected DiffRequest loadRequestFast(@NotNull DiffRequestProducer producer, boolean useCache) {
+    if (!useCache) return null;
     return myRequestCache.get(producer);
   }
 
index 6f657b49d5b218961de22355e26aca7d94178589..ba9f21e02cfe4a472f00be38f6f71006ef97ce44 100644 (file)
@@ -158,6 +158,11 @@ public abstract class DiffRequestProcessor implements Disposable {
   // Update
   //
 
+  @CalledInAwt
+  protected void reloadRequest() {
+    updateRequest(true);
+  }
+
   @CalledInAwt
   public void updateRequest() {
     updateRequest(false);
@@ -902,10 +907,15 @@ public abstract class DiffRequestProcessor implements Disposable {
     }
 
     @Override
-    public void reloadDiffRequest() {
+    public void reopenDiffRequest() {
       updateRequest(true);
     }
 
+    @Override
+    public void reloadDiffRequest() {
+      reloadRequest();
+    }
+
     @Nullable
     @Override
     public Project getProject() {
diff --git a/platform/diff-impl/src/com/intellij/diff/requests/UnknownFileTypeDiffRequest.java b/platform/diff-impl/src/com/intellij/diff/requests/UnknownFileTypeDiffRequest.java
new file mode 100644 (file)
index 0000000..53d0c74
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2015 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.requests;
+
+import com.intellij.diff.DiffContext;
+import com.intellij.diff.DiffContextEx;
+import com.intellij.diff.util.DiffUtil;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.fileTypes.UnknownFileType;
+import com.intellij.openapi.fileTypes.ex.FileTypeChooser;
+import com.intellij.openapi.vcs.changes.issueLinks.LinkMouseListenerBase;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.SimpleColoredComponent;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class UnknownFileTypeDiffRequest extends ComponentDiffRequest {
+  @Nullable private final String myFileName;
+  @Nullable private final String myTitle;
+
+  public UnknownFileTypeDiffRequest(@NotNull VirtualFile file, @Nullable String title) {
+    this(file.getName(), title);
+  }
+
+  public UnknownFileTypeDiffRequest(@NotNull String fileName, @Nullable String title) {
+    boolean knownFileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName) != UnknownFileType.INSTANCE;
+    myFileName = knownFileType ? null : fileName;
+    myTitle = title;
+  }
+
+  public UnknownFileTypeDiffRequest(@Nullable String title) {
+    myFileName = null;
+    myTitle = title;
+  }
+
+  @NotNull
+  @Override
+  public JComponent getComponent(@NotNull final DiffContext context) {
+    final SimpleColoredComponent label = new SimpleColoredComponent();
+    label.append("Can't show diff for unknown file type. ",
+                 new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, UIUtil.getInactiveTextColor()));
+    if (myFileName != null) {
+      label.append("Associate", SimpleTextAttributes.LINK_ATTRIBUTES, new Runnable() {
+        @Override
+        public void run() {
+          FileType type = FileTypeChooser.associateFileType(myFileName);
+          if (type != null) onSuccess(context);
+        }
+      });
+      LinkMouseListenerBase.installSingleTagOn(label);
+    }
+    return DiffUtil.createMessagePanel(label);
+  }
+
+  @Nullable
+  public String getFileName() {
+    return myFileName;
+  }
+
+  @Nullable
+  @Override
+  public String getTitle() {
+    return myTitle;
+  }
+
+  protected void onSuccess(@NotNull DiffContext context) {
+    if (context instanceof DiffContextEx) ((DiffContextEx)context).reloadDiffRequest();
+  }
+}
index 1d835bc583eda72717c5e2f84b0f8f46c49ff7f0..444990f0738678b31e2c629940aed68bcc4edcae 100644 (file)
@@ -20,19 +20,15 @@ import com.intellij.diff.DiffContextEx;
 import com.intellij.diff.FrameDiffTool;
 import com.intellij.diff.contents.DiffContent;
 import com.intellij.diff.contents.FileContent;
-import com.intellij.diff.requests.ContentDiffRequest;
-import com.intellij.diff.requests.DiffRequest;
-import com.intellij.diff.requests.MessageDiffRequest;
+import com.intellij.diff.requests.*;
 import com.intellij.diff.util.DiffUtil;
-import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.fileTypes.FileTypeManager;
 import com.intellij.openapi.fileTypes.FileTypes;
-import com.intellij.openapi.fileTypes.ex.FileTypeChooser;
-import com.intellij.openapi.vcs.changes.issueLinks.LinkMouseListenerBase;
+import com.intellij.openapi.fileTypes.UnknownFileType;
 import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.SimpleColoredComponent;
-import com.intellij.ui.SimpleTextAttributes;
 import com.intellij.util.ui.JBUI;
-import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -79,26 +75,17 @@ public class ErrorDiffTool implements FrameDiffTool {
         String message = ((MessageDiffRequest)request).getMessage();
         return DiffUtil.createMessagePanel(message);
       }
+      if (request instanceof ComponentDiffRequest) {
+        return ((ComponentDiffRequest)request).getComponent(myContext);
+      }
       if (request instanceof ContentDiffRequest) {
         List<DiffContent> contents = ((ContentDiffRequest)request).getContents();
-        for (DiffContent content : contents) {
+        for (final DiffContent content : contents) {
           if (content instanceof FileContent && FileTypes.UNKNOWN.equals(content.getContentType())) {
             final VirtualFile file = ((FileContent)content).getFile();
 
-            final SimpleColoredComponent label = new SimpleColoredComponent();
-            label.append("Can't show diff for unknown file type. ",
-                         new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, UIUtil.getInactiveTextColor()));
-            label.append("Associate", SimpleTextAttributes.LINK_ATTRIBUTES, new Runnable() {
-              @Override
-              public void run() {
-                FileType type = FileTypeChooser.associateFileType(file.getName());
-                if (type != null && myContext instanceof DiffContextEx) {
-                  ((DiffContextEx)myContext).reloadDiffRequest();
-                }
-              }
-            });
-            LinkMouseListenerBase.installSingleTagOn(label);
-            return DiffUtil.createMessagePanel(label);
+            UnknownFileTypeDiffRequest unknownFileTypeRequest = new UnknownFileTypeDiffRequest(file, myRequest.getTitle());
+            return unknownFileTypeRequest.getComponent(myContext);
           }
         }
       }
@@ -121,6 +108,21 @@ public class ErrorDiffTool implements FrameDiffTool {
     @NotNull
     @Override
     public ToolbarComponents init() {
+      if (myRequest instanceof UnknownFileTypeDiffRequest) {
+        String fileName = ((UnknownFileTypeDiffRequest)myRequest).getFileName();
+        if (fileName != null && FileTypeManager.getInstance().getFileTypeByFileName(fileName) != UnknownFileType.INSTANCE) {
+          // FileType was assigned elsewhere (ex: by other UnknownFileTypeDiffRequest). We should reload request.
+          if (myContext instanceof DiffContextEx) {
+            ApplicationManager.getApplication().invokeLater(new Runnable() {
+              @Override
+              public void run() {
+                ((DiffContextEx)myContext).reloadDiffRequest();
+              }
+            }, ModalityState.current());
+          }
+        }
+      }
+
       return new ToolbarComponents();
     }
 
index 51a8bd778654f5a1cff283d2bbc0ed6fc6893867..601be4e3eb679635a377a1db1fc436819fd397f9 100644 (file)
@@ -74,11 +74,21 @@ public abstract class CacheChangeProcessor extends DiffRequestProcessor {
   // Update
   //
 
+  @Override
+  protected void reloadRequest() {
+    updateRequest(true, false, null);
+  }
+
   @CalledInAwt
   public void updateRequest(final boolean force, @Nullable final ScrollToPolicy scrollToChangePolicy) {
+    updateRequest(force, true, scrollToChangePolicy);
+  }
+
+  @CalledInAwt
+  public void updateRequest(final boolean force, boolean useCache, @Nullable final ScrollToPolicy scrollToChangePolicy) {
     final Change change = myCurrentChange;
 
-    DiffRequest cachedRequest = loadRequestFast(change);
+    DiffRequest cachedRequest = loadRequestFast(change, useCache);
     if (cachedRequest != null) {
       applyRequest(cachedRequest, force, scrollToChangePolicy);
       return;
@@ -112,15 +122,17 @@ public abstract class CacheChangeProcessor extends DiffRequestProcessor {
 
   @Nullable
   @CalledInAwt
-  @Contract("null -> !null")
-  protected DiffRequest loadRequestFast(@Nullable Change change) {
+  @Contract("null, _ -> !null")
+  protected DiffRequest loadRequestFast(@Nullable Change change, boolean useCache) {
     if (change == null) return NoDiffRequest.INSTANCE;
 
-    Pair<Change, DiffRequest> pair = myRequestCache.get(change);
-    if (pair != null) {
-      Change oldChange = pair.first;
-      if (ChangeDiffRequestProducer.isEquals(oldChange, change)) {
-        return pair.second;
+    if (useCache) {
+      Pair<Change, DiffRequest> pair = myRequestCache.get(change);
+      if (pair != null) {
+        Change oldChange = pair.first;
+        if (ChangeDiffRequestProducer.isEquals(oldChange, change)) {
+          return pair.second;
+        }
       }
     }
 
index 27cd16abd90fa7cb486a16b8e813b2dfa43bb326..4eb32f5a2146e2e8825bc7ae5fc3377cb56ecd18 100644 (file)
@@ -20,8 +20,10 @@ import com.intellij.diff.chains.DiffRequestProducerException;
 import com.intellij.diff.contents.DocumentContent;
 import com.intellij.diff.requests.DiffRequest;
 import com.intellij.diff.requests.SimpleDiffRequest;
+import com.intellij.diff.requests.UnknownFileTypeDiffRequest;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.UnknownFileType;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.Getter;
index 39a9d71e0ea3bf5e6bd8965f41eb0a3c44c75b3b..71c1d1c5b16512ec9108295a840ba40bfe367af3 100644 (file)
@@ -18,10 +18,12 @@ package com.intellij.openapi.vcs.changes.patch;
 import com.intellij.diff.chains.DiffRequestProducer;
 import com.intellij.diff.chains.DiffRequestProducerException;
 import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.requests.UnknownFileTypeDiffRequest;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diff.impl.patch.FilePatch;
 import com.intellij.openapi.diff.impl.patch.PatchReader;
 import com.intellij.openapi.diff.impl.patch.TextFilePatch;
+import com.intellij.openapi.fileTypes.UnknownFileType;
 import com.intellij.openapi.progress.ProcessCanceledException;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.project.Project;
@@ -87,6 +89,10 @@ public class TextFilePatchInProgress extends AbstractFilePatchInProgress<TextFil
       @Override
       public DiffRequest process(@NotNull UserDataHolder context, @NotNull ProgressIndicator indicator)
         throws DiffRequestProducerException, ProcessCanceledException {
+        if (myCurrentBase != null && myCurrentBase.getFileType() == UnknownFileType.INSTANCE) {
+          return new UnknownFileTypeDiffRequest(myCurrentBase, getName());
+        }
+
         if (isConflictingChange()) {
           final VirtualFile file = getCurrentBase();
 
index 1defa4924cbe76c0e94fdec3ca217d43eebf9fac..6b75622dc17ec9e4c167a98c125ab5c8958f16fb 100644 (file)
@@ -22,6 +22,7 @@ import com.intellij.diff.chains.DiffRequestChain;
 import com.intellij.diff.chains.DiffRequestProducer;
 import com.intellij.diff.chains.DiffRequestProducerException;
 import com.intellij.diff.requests.DiffRequest;
+import com.intellij.diff.requests.UnknownFileTypeDiffRequest;
 import com.intellij.openapi.actionSystem.AnAction;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.CommonDataKeys;
@@ -29,6 +30,7 @@ import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.diff.impl.patch.*;
 import com.intellij.openapi.diff.impl.patch.apply.ApplyFilePatchBase;
 import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.fileTypes.UnknownFileType;
 import com.intellij.openapi.progress.ProcessCanceledException;
 import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.project.DumbAware;
@@ -192,6 +194,10 @@ public class DiffShelvedChangesAction extends AnAction implements DumbAware {
         @Override
         public DiffRequest process(@NotNull UserDataHolder context, @NotNull ProgressIndicator indicator)
           throws DiffRequestProducerException, ProcessCanceledException {
+          if (file != null && file.getFileType() == UnknownFileType.INSTANCE) {
+            return new UnknownFileTypeDiffRequest(file, getName());
+          }
+
           if (shelvedChange.isConflictingChange(project)) {
             try {
               final CommitContext commitContext = new CommitContext();