From 7053313c86268ac956af26834ec6ebbeac85fd8f Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 29 May 2013 21:17:27 +0400 Subject: [PATCH] IDEA-107827 (do not lose a document after renaming a file to an unknown type) --- .../impl/FileDocumentManagerImpl.java | 46 +++++++------ .../RealFileDocumentManagerTest.java | 67 +++++++++++++++++++ .../com/intellij/reference/SoftReference.java | 3 +- .../intellij/openapi/util/io/IoTestUtil.java | 8 ++- 4 files changed, 102 insertions(+), 22 deletions(-) create mode 100644 platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/RealFileDocumentManagerTest.java diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java index 84e7d50bd60a..52f10a0ccbc7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileDocumentManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -41,6 +41,8 @@ import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.fileEditor.impl.text.TextEditorImpl; import com.intellij.openapi.fileTypes.BinaryFileTypeDecompilers; import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.fileTypes.UnknownFileType; import com.intellij.openapi.project.*; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.ui.DialogBuilder; @@ -79,6 +81,8 @@ import java.lang.reflect.Proxy; import java.util.*; import java.util.List; +import static com.intellij.reference.SoftReference.dereference; + public class FileDocumentManagerImpl extends FileDocumentManager implements ApplicationComponent, VirtualFileListener, ProjectManagerListener, SafeWriteRequestor { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl"); @@ -226,16 +230,7 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl @Override @Nullable public Document getCachedDocument(@NotNull VirtualFile file) { - Reference reference = file.getUserData(DOCUMENT_KEY); - Document document = reference == null ? null : reference.get(); - - if (document != null && isBinaryWithoutDecompiler(file)) { - file.putUserData(DOCUMENT_KEY, null); - document.putUserData(FILE_KEY, null); - return null; - } - - return document; + return dereference(file.getUserData(DOCUMENT_KEY)); } public static void registerDocument(@NotNull final Document document, @NotNull VirtualFile virtualFile) { @@ -536,21 +531,32 @@ public class FileDocumentManagerImpl extends FileDocumentManager implements Appl } @Override - public void propertyChanged(final VirtualFilePropertyEvent event) { + public void propertyChanged(VirtualFilePropertyEvent event) { + final VirtualFile file = event.getFile(); if (VirtualFile.PROP_WRITABLE.equals(event.getPropertyName())) { - final VirtualFile file = event.getFile(); final Document document = getCachedDocument(file); - if (document == null) return; - - ApplicationManager.getApplication().runWriteAction( - new ExternalChangeAction() { + if (document != null) { + ApplicationManager.getApplication().runWriteAction(new ExternalChangeAction() { @Override public void run() { - document.setReadOnly(!event.getFile().isWritable()); + document.setReadOnly(!file.isWritable()); } + }); + } + } + else if (VirtualFile.PROP_NAME.equals(event.getPropertyName())) { + Document document = getCachedDocument(file); + if (document != null) { + FileType type = file.getFileType(); + if (type == UnknownFileType.INSTANCE) { + // a file is linked to a document - chances are it is an "unknown text file" now + FileTypeManager.getInstance().detectFileTypeFromContent(file); } - ); - //myUnsavedDocuments.remove(document); //? + if (isBinaryWithoutDecompiler(file)) { + file.putUserData(DOCUMENT_KEY, null); + document.putUserData(FILE_KEY, null); + } + } } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/RealFileDocumentManagerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/RealFileDocumentManagerTest.java new file mode 100644 index 000000000000..fca92e9ab14c --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/RealFileDocumentManagerTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2013 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.openapi.fileEditor; + +import com.intellij.openapi.application.AccessToken; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.io.IoTestUtil; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.LightPlatformLangTestCase; + +import java.io.File; +import java.io.IOException; + +public class RealFileDocumentManagerTest extends LightPlatformLangTestCase { + public void testFileTypeModificationDocumentPreservation() throws Exception { + File ioFile = IoTestUtil.createTestFile("test.html", "some text"); + VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile); + assertNotNull(ioFile.getPath(), file); + + FileDocumentManager documentManager = FileDocumentManager.getInstance(); + Document original = documentManager.getDocument(file); + assertNotNull(file.getPath(), original); + + renameFile(file, "test.wtf"); + Document afterRename = documentManager.getDocument(file); + assertTrue(afterRename + " != " + original, afterRename == original); + } + + public void testFileTypeChangeDocumentDetach() throws Exception { + File ioFile = IoTestUtil.createTestFile("test.html", "some text"); + VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile); + assertNotNull(ioFile.getPath(), file); + + FileDocumentManager documentManager = FileDocumentManager.getInstance(); + Document original = documentManager.getDocument(file); + assertNotNull(file.getPath(), original); + + renameFile(file, "test.png"); + Document afterRename = documentManager.getDocument(file); + assertNull(afterRename + " != null", afterRename); + } + + private static void renameFile(VirtualFile file, String newName) throws IOException { + AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(RealFileDocumentManagerTest.class); + try { + file.rename(RealFileDocumentManagerTest.class, newName); + } + finally { + token.finish(); + } + } +} diff --git a/platform/util-rt/src/com/intellij/reference/SoftReference.java b/platform/util-rt/src/com/intellij/reference/SoftReference.java index f28f94834690..260efdecac78 100644 --- a/platform/util-rt/src/com/intellij/reference/SoftReference.java +++ b/platform/util-rt/src/com/intellij/reference/SoftReference.java @@ -17,6 +17,7 @@ package com.intellij.reference; import org.jetbrains.annotations.Nullable; +import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; /** @@ -46,7 +47,7 @@ public class SoftReference extends java.lang.ref.SoftReference { //} @Nullable - public static T dereference(@Nullable java.lang.ref.SoftReference ref) { + public static T dereference(@Nullable Reference ref) { return ref != null ? ref.get() : null; } } diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java b/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java index 7c08a7752666..7c88491d8a1e 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java +++ b/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java @@ -237,7 +237,12 @@ public class IoTestUtil { @NotNull public static File createTestFile(@NotNull String name) throws IOException { - return createTestFile(new File(FileUtil.getTempDirectory()), name, null); + return createTestFile(name, null); + } + + @NotNull + public static File createTestFile(@NotNull String name, @Nullable String content) throws IOException { + return createTestFile(new File(FileUtil.getTempDirectory()), name, content); } @NotNull @@ -247,6 +252,7 @@ public class IoTestUtil { @NotNull public static File createTestFile(@NotNull File parent, @NotNull String name, @Nullable String content) throws IOException { + assertTrue(parent.getPath(), parent.isDirectory() || parent.mkdirs()); File file = new File(parent, name); assertTrue(file.getPath(), file.createNewFile()); if (content != null) {